Repository: prebid/prebid-server
Pull request #2337 (2022-08-03 18:49:09)

Add account-specific error metrics to setuid endpoint
This PR makes the setuid endpoint consistent with the cookie sync endpoint in how it reports account-related error metrics. Instead of always reporting "bad request" when there is an account error, we now indicate whether the account was blocked, or invalid before defaulting to "bad request".
Also a few changes were made to ensure any errors encountered by the setuid endpoint are appropriately logged when calling the analytic adapter `LogSetUIDObject` function.


Patch:
diff --git a/adapters/33across/33across.go b/adapters/33across/33across.go
index 72b91059..a0207f4a 100644
--- a/adapters/33across/33across.go
+++ b/adapters/33across/33across.go
@@ -48,7 +48,7 @@ type bidExt struct {
 }
 
 type bidTtxExt struct {
-	MediaType string `json:mediaType,omitempty`
+	MediaType string `json:"mediaType,omitempty"`
 }
 
 // MakeRequests create the object for TTX Reqeust.
diff --git a/adapters/adrino/adrino.go b/adapters/adrino/adrino.go
new file mode 100644
index 00000000..d9fe448a
--- /dev/null
+++ b/adapters/adrino/adrino.go
@@ -0,0 +1,85 @@
+package adrino
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb/v16/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	endpoint string
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var errs []error
+
+	reqJson, err := json.Marshal(request)
+	if err != nil {
+		errs = append(errs, err)
+		return nil, errs
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+
+	return []*adapters.RequestData{{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    reqJson,
+		Headers: headers,
+	}}, errs
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var errs []error
+
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if response.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponse()
+	bidResponse.Currency = bidResp.Cur
+
+	for _, seatBid := range bidResp.SeatBid {
+		for i := range seatBid.Bid {
+			bidType := openrtb_ext.BidTypeNative // our adserver supports only native ads
+			b := &adapters.TypedBid{
+				Bid:     &seatBid.Bid[i],
+				BidType: bidType,
+			}
+			bidResponse.Bids = append(bidResponse.Bids, b)
+		}
+	}
+	return bidResponse, errs
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
diff --git a/adapters/adtrgtme/adtrgtme.go b/adapters/adtrgtme/adtrgtme.go
new file mode 100644
index 00000000..7a099372
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtme.go
@@ -0,0 +1,197 @@
+package adtrgtme
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb/v16/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 Adtrgtme 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 (v *adapter) MakeRequests(
+	openRTBRequest *openrtb2.BidRequest,
+	requestInfo *adapters.ExtraRequestInfo,
+) (
+	[]*adapters.RequestData,
+	[]error,
+) {
+	var requests []*adapters.RequestData
+	var errors []error
+
+	requestCopy := *openRTBRequest
+
+	for _, imp := range openRTBRequest.Imp {
+		requestCopy.Imp = []openrtb2.Imp{imp}
+
+		requestJSON, err := json.Marshal(openRTBRequest)
+		if err != nil {
+			errors = append(errors, err)
+			continue
+		}
+
+		requestURI, err := v.buildRequestURI(&requestCopy)
+		if err != nil {
+			errors = append(errors, err)
+			continue
+		}
+
+		requestData := &adapters.RequestData{
+			Method:  http.MethodPost,
+			Uri:     requestURI,
+			Body:    requestJSON,
+			Headers: makeRequestHeaders(&requestCopy),
+		}
+
+		requests = append(requests, requestData)
+	}
+
+	return requests, errors
+}
+
+func (v *adapter) buildRequestURI(openRTBRequest *openrtb2.BidRequest) (string, error) {
+	if openRTBRequest.Site != nil {
+		if openRTBRequest.Site.ID != "" {
+			return fmt.Sprintf("%s?s=%s&prebid", v.endpoint, openRTBRequest.Site.ID), nil
+		}
+		return "", &errortypes.BadInput{
+			Message: "request.Site.ID is not provided",
+		}
+	} else if openRTBRequest.App != nil {
+		if openRTBRequest.App.ID != "" {
+			return fmt.Sprintf("%s?s=%s&prebid", v.endpoint, openRTBRequest.App.ID), nil
+		}
+		return "", &errortypes.BadInput{
+			Message: "request.App.ID is not provided",
+		}
+	}
+	return "", &errortypes.BadInput{
+		Message: "request.Site or request.App are not provided",
+	}
+}
+
+func makeRequestHeaders(openRTBRequest *openrtb2.BidRequest) http.Header {
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("X-Openrtb-Version", "2.5")
+
+	if openRTBRequest.Device != nil {
+		if len(openRTBRequest.Device.UA) > 0 {
+			headers.Add("User-Agent", openRTBRequest.Device.UA)
+		}
+
+		if len(openRTBRequest.Device.IPv6) > 0 {
+			headers.Add("X-Forwarded-For", openRTBRequest.Device.IPv6)
+		}
+
+		if len(openRTBRequest.Device.IP) > 0 {
+			headers.Add("X-Forwarded-For", openRTBRequest.Device.IP)
+		}
+	}
+	return headers
+}
+
+func (v *adapter) checkResponseStatusCodes(response *adapters.ResponseData) error {
+	if response.StatusCode == http.StatusBadRequest {
+		return &errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: [ %d ]", response.StatusCode),
+		}
+	}
+
+	if response.StatusCode == http.StatusServiceUnavailable {
+		return &errortypes.BadInput{
+			Message: fmt.Sprintf("Something went wrong, please contact your Account Manager. Status Code: [ %d ] ", response.StatusCode),
+		}
+	}
+
+	if response.StatusCode != http.StatusOK {
+		return &errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: [ %d ]. Run with request.debug = 1 for more info", response.StatusCode),
+		}
+	}
+
+	return nil
+}
+
+func (v *adapter) MakeBids(
+	openRTBRequest *openrtb2.BidRequest,
+	requestToBidder *adapters.RequestData,
+	bidderRawResponse *adapters.ResponseData,
+) (
+	*adapters.BidderResponse,
+	[]error,
+) {
+	if bidderRawResponse.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	httpStatusError := v.checkResponseStatusCodes(bidderRawResponse)
+	if httpStatusError != nil {
+		return nil, []error{httpStatusError}
+	}
+
+	var response openrtb2.BidResponse
+	if err := json.Unmarshal(bidderRawResponse.Body, &response); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Bad Server Response",
+		}}
+	}
+
+	if len(response.SeatBid) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid array",
+		}}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(openRTBRequest.Imp))
+	bidResponse.Currency = response.Cur
+	for _, seatBid := range response.SeatBid {
+		for i, bid := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(bid.ImpID, openRTBRequest.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
+			} else {
+				return "", &errortypes.BadInput{
+					Message: fmt.Sprintf("Unsupported bidtype for bid: \"%s\"", impId),
+				}
+			}
+		}
+	}
+	return "", &errortypes.BadInput{
+		Message: fmt.Sprintf("Failed to find impression: \"%s\"", impId),
+	}
+}
diff --git a/adapters/pubmatic/pubmatic.go b/adapters/pubmatic/pubmatic.go
index 61b0105e..802806da 100644
--- a/adapters/pubmatic/pubmatic.go
+++ b/adapters/pubmatic/pubmatic.go
@@ -7,6 +7,7 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/buger/jsonparser"
 	"github.com/golang/glog"
 	"github.com/mxmCherry/openrtb/v16/openrtb2"
 	"github.com/prebid/prebid-server/adapters"
@@ -235,8 +236,8 @@ func parseImpressionObject(imp *openrtb2.Imp, extractWrapperExtFromImp, extractP
 	var pubID string
 
 	// PubMatic supports banner and video impressions.
-	if imp.Banner == nil && imp.Video == nil {
-		return wrapExt, pubID, fmt.Errorf("Invalid MediaType. PubMatic only supports Banner and Video. Ignoring ImpID=%s", imp.ID)
+	if imp.Banner == nil && imp.Video == nil && imp.Native == nil {
+		return wrapExt, pubID, fmt.Errorf("invalid MediaType. PubMatic only supports Banner, Video and Native. Ignoring ImpID=%s", imp.ID)
 	}
 
 	if imp.Audio != nil {
@@ -394,13 +395,23 @@ func (a *PubmaticAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externa
 			seat := ""
 			var bidExt *pubmaticBidExt
 			bidType := openrtb_ext.BidTypeBanner
-			if err := json.Unmarshal(bid.Ext, &bidExt); err == nil && bidExt != nil {
+			err := json.Unmarshal(bid.Ext, &bidExt)
+			if err != nil {
+				errs = append(errs, err)
+			} else if bidExt != nil {
 				seat = bidExt.Marketplace
 				if bidExt.VideoCreativeInfo != nil && bidExt.VideoCreativeInfo.Duration != nil {
 					impVideo.Duration = *bidExt.VideoCreativeInfo.Duration
 				}
 				bidType = getBidType(bidExt)
 			}
+
+			if bidType == openrtb_ext.BidTypeNative {
+				if value, _, _, err := jsonparser.Get([]byte(bid.AdM), string(openrtb_ext.BidTypeNative)); err == nil {
+					bid.AdM = string(value)
+				}
+			}
+
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
 				Bid:      &bid,
 				BidType:  bidType,
diff --git a/config/accounts.go b/config/accounts.go
index 7d954c0c..8705b167 100644
--- a/config/accounts.go
+++ b/config/accounts.go
@@ -232,6 +232,7 @@ type AlternateBidderCodes struct {
 }
 
 type AdapterAlternateBidderCodes struct {
+	Enabled            bool     `mapstructure:"enabled" json:"enabled"`
 	AllowedBidderCodes []string `mapstructure:"allowedbiddercodes" json:"allowedbiddercodes"`
 }
 
@@ -255,11 +256,12 @@ func (bidderCodes *AlternateBidderCodes) IsValidBidderCode(bidder, alternateBidd
 		return false, fmt.Errorf(ErrAlternateBidderNotDefined, bidder, alternateBidder)
 	}
 
-	if len(adapterCfg.AllowedBidderCodes) == 0 {
+	if !adapterCfg.Enabled {
+		// config has bidder entry but is not enabled, report it
 		return false, fmt.Errorf("alternateBidderCodes disabled for %q, rejecting bids for %q", bidder, alternateBidder)
 	}
 
-	if adapterCfg.AllowedBidderCodes[0] == "*" {
+	if adapterCfg.AllowedBidderCodes == nil || (len(adapterCfg.AllowedBidderCodes) == 1 && adapterCfg.AllowedBidderCodes[0] == "*") {
 		return true, nil
 	}
 
diff --git a/config/config.go b/config/config.go
index b602cf90..591fded9 100644
--- a/config/config.go
+++ b/config/config.go
@@ -935,7 +935,9 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.adot.endpoint", "https://dsp.adotmob.com/headerbidding{PUBLISHER_PATH}/bidrequest")
 	v.SetDefault("adapters.adpone.endpoint", "http://rtb.adpone.com/bid-request?src=prebid_server")
 	v.SetDefault("adapters.adprime.endpoint", "http://delta.adprime.com/pserver")
+	v.SetDefault("adapters.adrino.endpoint", "https://prd-prebid-bidder.adrino.io/openrtb/bid")
 	v.SetDefault("adapters.adtarget.endpoint", "http://ghb.console.adtarget.com.tr/pbs/ortb")
+	v.SetDefault("adapters.adtrgtme.endpoint", "https://z.cdn.adtarget.market/ssp")
 	v.SetDefault("adapters.adtelligent.endpoint", "http://ghb.adtelligent.com/pbs/ortb")
 	v.SetDefault("adapters.advangelists.endpoint", "http://nep.advangelists.com/xp/get?pubid={{.PublisherID}}")
 	v.SetDefault("adapters.adview.endpoint", "https://bid.adview.com/agent/thirdAdxService/{{.AccountID}}")
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 0598da7b..43dc7a10 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -1526,6 +1526,10 @@ func setAuctionTypeImplicitly(bidReq *openrtb2.BidRequest) {
 func setSiteImplicitly(httpReq *http.Request, bidReq *openrtb2.BidRequest) {
 	if bidReq.Site == nil || bidReq.Site.Page == "" || bidReq.Site.Domain == "" {
 		referrerCandidate := httpReq.Referer()
+		// If http referer is disabled and thus has empty value - use site.page instead
+		if referrerCandidate == "" && bidReq.Site != nil && bidReq.Site.Page != "" {
+			referrerCandidate = bidReq.Site.Page
+		}
 		if parsedUrl, err := url.Parse(referrerCandidate); err == nil {
 			if domain, err := publicsuffix.EffectiveTLDPlusOne(parsedUrl.Host); err == nil {
 				if bidReq.Site == nil {
@@ -1681,7 +1685,6 @@ func (deps *endpointDeps) processStoredRequests(ctx context.Context, requestJson
 				return nil, nil, []error{err}
 			}
 			resolvedImps = append(resolvedImps, resolvedImp)
-
 			impId, err := jsonparser.GetString(resolvedImp, "id")
 			if err != nil {
 				return nil, nil, []error{err}
@@ -1691,12 +1694,25 @@ func (deps *endpointDeps) processStoredRequests(ctx context.Context, requestJson
 			if impData.ImpExtPrebid.Options != nil {
 				echoVideoAttributes = impData.ImpExtPrebid.Options.EchoVideoAttrs
 			}
-			impExtInfoMap[impId] = exchange.ImpExtInfo{EchoVideoAttrs: echoVideoAttributes, StoredImp: storedImps[impData.ImpExtPrebid.StoredRequest.ID]}
+
+			// Extract Passthrough from Merged Imp
+			passthrough, _, _, err := jsonparser.Get(resolvedImp, "ext", "prebid", "passthrough")
+			if err != nil && err != jsonparser.KeyPathNotFoundError {
+				return nil, nil, []error{err}
+			}
+			impExtInfoMap[impId] = exchange.ImpExtInfo{EchoVideoAttrs: echoVideoAttributes, StoredImp: storedImps[impData.ImpExtPrebid.StoredRequest.ID], Passthrough: passthrough}
 
 		} else {
 			resolvedImps = append(resolvedImps, impData.Imp)
+			impId, err := jsonparser.GetString(impData.Imp, "id")
+			if err != nil {
+				if err == jsonparser.KeyPathNotFoundError {
+					err = fmt.Errorf("request.imp[%d] missing required field: \"id\"\n", i)
+				}
+				return nil, nil, []error{err}
+			}
+			impExtInfoMap[impId] = exchange.ImpExtInfo{Passthrough: impData.ImpExtPrebid.Passthrough}
 		}
-
 	}
 	if len(resolvedImps) > 0 {
 		newImpJson, err := json.Marshal(resolvedImps)
@@ -1714,7 +1730,6 @@ func (deps *endpointDeps) processStoredRequests(ctx context.Context, requestJson
 
 // parseImpInfo parses the request JSON and returns impression and unmarshalled imp.ext.prebid
 func parseImpInfo(requestJson []byte) (impData []ImpExtPrebidData, errs []error) {
-
 	if impArray, dataType, _, err := jsonparser.Get(requestJson, "imp"); err == nil && dataType == jsonparser.Array {
 		_, err = jsonparser.ArrayEach(impArray, func(imp []byte, _ jsonparser.ValueType, _ int, err error) {
 			impExtData, _, _, err := jsonparser.Get(imp, "ext", "prebid")
diff --git a/endpoints/setuid.go b/endpoints/setuid.go
index 716044a2..712178a0 100644
--- a/endpoints/setuid.go
+++ b/endpoints/setuid.go
@@ -61,6 +61,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 			w.WriteHeader(http.StatusBadRequest)
 			w.Write([]byte(err.Error()))
 			metricsEngine.RecordSetUid(metrics.SetUidSyncerUnknown)
+			so.Errors = []error{err}
 			so.Status = http.StatusBadRequest
 			return
 		}
@@ -71,6 +72,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 			w.WriteHeader(http.StatusBadRequest)
 			w.Write([]byte(err.Error()))
 			metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
+			so.Errors = []error{err}
 			so.Status = http.StatusBadRequest
 			return
 		}
@@ -82,8 +84,17 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 		account, fetchErrs := accountService.GetAccount(context.Background(), cfg, accountsFetcher, accountID)
 		if len(fetchErrs) > 0 {
 			w.WriteHeader(http.StatusBadRequest)
-			w.Write([]byte(combineErrors(fetchErrs).Error()))
-			metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
+			err := combineErrors(fetchErrs)
+			w.Write([]byte(err.Error()))
+			switch err {
+			case errCookieSyncAccountBlocked:
+				metricsEngine.RecordSetUid(metrics.SetUidAccountBlocked)
+			case errCookieSyncAccountInvalid:
+				metricsEngine.RecordSetUid(metrics.SetUidAccountInvalid)
+			default:
+				metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
+			}
+			so.Errors = []error{err}
 			so.Status = http.StatusBadRequest
 			return
 		}
@@ -99,6 +110,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 			case http.StatusUnavailableForLegalReasons:
 				metricsEngine.RecordSetUid(metrics.SetUidGDPRHostCookieBlocked)
 			}
+			so.Errors = []error{errors.New(body)}
 			so.Status = status
 			return
 		}
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 68c55793..765e1715 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -19,8 +19,10 @@ import (
 	"github.com/prebid/prebid-server/adapters/adot"
 	"github.com/prebid/prebid-server/adapters/adpone"
 	"github.com/prebid/prebid-server/adapters/adprime"
+	"github.com/prebid/prebid-server/adapters/adrino"
 	"github.com/prebid/prebid-server/adapters/adtarget"
 	"github.com/prebid/prebid-server/adapters/adtelligent"
+	"github.com/prebid/prebid-server/adapters/adtrgtme"
 	"github.com/prebid/prebid-server/adapters/advangelists"
 	"github.com/prebid/prebid-server/adapters/adview"
 	"github.com/prebid/prebid-server/adapters/adxcg"
@@ -169,7 +171,9 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderAdot:              adot.Builder,
 		openrtb_ext.BidderAdpone:            adpone.Builder,
 		openrtb_ext.BidderAdprime:           adprime.Builder,
+		openrtb_ext.BidderAdrino:            adrino.Builder,
 		openrtb_ext.BidderAdtarget:          adtarget.Builder,
+		openrtb_ext.BidderAdtrgtme:          adtrgtme.Builder,
 		openrtb_ext.BidderAdtelligent:       adtelligent.Builder,
 		openrtb_ext.BidderAdvangelists:      advangelists.Builder,
 		openrtb_ext.BidderAdView:            adview.Builder,
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 5ce0a1a5..f1a9a7b8 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -153,6 +153,7 @@ func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid
 type ImpExtInfo struct {
 	EchoVideoAttrs bool
 	StoredImp      []byte
+	Passthrough    json.RawMessage
 }
 
 // AuctionRequest holds the bid request for the auction
@@ -330,7 +331,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
 				errs = append(errs, dealErrs...)
 			}
 
-			bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, r, responseDebugAllow, errs)
+			bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, r, responseDebugAllow, requestExt.Prebid.Passthrough, errs)
 			if debugLog.DebugEnabledOrOverridden {
 				if bidRespExtBytes, err := json.Marshal(bidResponseExt); err == nil {
 					debugLog.Data.Response = string(bidRespExtBytes)
@@ -348,9 +349,9 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
 			targData.setTargeting(auc, r.BidRequestWrapper.BidRequest.App != nil, bidCategory, r.Account.TruncateTargetAttribute)
 
 		}
-		bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, r, responseDebugAllow, errs)
+		bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, r, responseDebugAllow, requestExt.Prebid.Passthrough, errs)
 	} else {
-		bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, r, responseDebugAllow, errs)
+		bidResponseExt = e.makeExtBidResponse(adapterBids, adapterExtra, r, responseDebugAllow, requestExt.Prebid.Passthrough, errs)
 
 		if debugLog.DebugEnabledOrOverridden {
 
@@ -943,8 +944,7 @@ func getPrimaryAdServer(adServerId int) (string, error) {
 }
 
 // Extract all the data from the SeatBids and build the ExtBidResponse
-func (e *exchange) makeExtBidResponse(adapterBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, r AuctionRequest, debugInfo bool, errList []error) *openrtb_ext.ExtBidResponse {
-
+func (e *exchange) makeExtBidResponse(adapterBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, r AuctionRequest, debugInfo bool, passthrough json.RawMessage, errList []error) *openrtb_ext.ExtBidResponse {
 	bidResponseExt := &openrtb_ext.ExtBidResponse{
 		Errors:               make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage, len(adapterBids)),
 		Warnings:             make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage, len(adapterBids)),
@@ -964,6 +964,13 @@ func (e *exchange) makeExtBidResponse(adapterBids map[openrtb_ext.BidderName]*pb
 		}
 	}
 
+	if passthrough != nil {
+		if bidResponseExt.Prebid == nil {
+			bidResponseExt.Prebid = &openrtb_ext.ExtResponsePrebid{}
+		}
+		bidResponseExt.Prebid.Passthrough = passthrough
+	}
+
 	for bidderName, responseExtra := range adapterExtra {
 
 		if debugInfo && len(responseExtra.HttpCalls) > 0 {
@@ -1072,20 +1079,22 @@ func makeBidExtJSON(ext json.RawMessage, prebid *openrtb_ext.ExtBidPrebid, impEx
 		}
 		prebid.Meta = &metaContainer.Prebid.Meta
 	}
-	extMap[openrtb_ext.PrebidExtKey] = prebid
 
-	// ext.storedrequestattributes
-	if impExtInfo, ok := impExtInfoMap[impId]; ok && impExtInfo.EchoVideoAttrs {
-		videoData, _, _, err := jsonparser.Get(impExtInfo.StoredImp, "video")
-		if err != nil && err != jsonparser.KeyPathNotFoundError {
-			return nil, err
-		}
-		//handler for case where EchoVideoAttrs is true, but video data is not found
-		if len(videoData) > 0 {
-			extMap[openrtb_ext.StoredRequestAttributes] = json.RawMessage(videoData)
+	// ext.prebid.storedrequestattributes and ext.prebid.passthrough
+	if impExtInfo, ok := impExtInfoMap[impId]; ok {
+		prebid.Passthrough = impExtInfoMap[impId].Passthrough
+		if impExtInfo.EchoVideoAttrs {
+			videoData, _, _, err := jsonparser.Get(impExtInfo.StoredImp, "video")
+			if err != nil && err != jsonparser.KeyPathNotFoundError {
+				return nil, err
+			}
+			//handler for case where EchoVideoAttrs is true, but video data is not found
+			if len(videoData) > 0 {
+				extMap[openrtb_ext.StoredRequestAttributes] = json.RawMessage(videoData)
+			}
 		}
 	}
-
+	extMap[openrtb_ext.PrebidExtKey] = prebid
 	return json.Marshal(extMap)
 }
 
diff --git a/exchange/utils.go b/exchange/utils.go
index 8a4e0b68..96e5e2a9 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -3,14 +3,14 @@ package exchange
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"math/rand"
 
-	"github.com/prebid/prebid-server/stored_responses"
-
 	"github.com/buger/jsonparser"
 	"github.com/mxmCherry/openrtb/v16/openrtb2"
 	"github.com/prebid/go-gdpr/vendorconsent"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/firstpartydata"
@@ -21,6 +21,7 @@ import (
 	"github.com/prebid/prebid-server/privacy/ccpa"
 	"github.com/prebid/prebid-server/privacy/lmt"
 	"github.com/prebid/prebid-server/schain"
+	"github.com/prebid/prebid-server/stored_responses"
 )
 
 var integrationTypeMap = map[metrics.RequestType]config.IntegrationType{
@@ -55,7 +56,7 @@ func cleanOpenRTBRequests(ctx context.Context,
 		return
 	}
 
-	allowedBidderRequests = make([]BidderRequest, 0, 0)
+	allowedBidderRequests = make([]BidderRequest, 0)
 
 	bidderImpWithBidResp := stored_responses.InitStoredBidResponses(req.BidRequest, auctionReq.StoredBidResponses)
 
@@ -217,7 +218,7 @@ func getAuctionBidderRequests(auctionRequest AuctionRequest,
 		return nil, []error{err}
 	}
 
-	bidderParamsInReqExt, err := adapters.ExtractReqExtBidderParamsEmbeddedMap(req.BidRequest)
+	bidderParamsInReqExt, err := adapters.ExtractReqExtBidderParamsMap(req.BidRequest)
 	if err != nil {
 		return nil, []error{err}
 	}
@@ -236,23 +237,10 @@ func getAuctionBidderRequests(auctionRequest AuctionRequest,
 
 		sChainWriter.Write(&reqCopy, bidder)
 
-		if len(bidderParamsInReqExt) != 0 {
-
-			// Update bidder-params(requestExt.Prebid.BidderParams) for the bidder to only contain bidder-params for
-			// this bidder only and remove bidder-params for all other bidders from requestExt.Prebid.BidderParams
-			params, err := getBidderParamsForBidder(bidderParamsInReqExt, bidder)
-			if err != nil {
-				return nil, []error{err}
-			}
-
-			requestExt.Prebid.BidderParams = params
-		}
-
-		reqExt, err := getExtJson(req.BidRequest, requestExt)
+		reqCopy.Ext, err = buildRequestExtForBidder(bidder, req.BidRequest.Ext, requestExt, bidderParamsInReqExt)
 		if err != nil {
 			return nil, []error{err}
 		}
-		reqCopy.Ext = reqExt
 
 		if err := removeUnpermissionedEids(&reqCopy, bidder, requestExt); err != nil {
 			errs = append(errs, fmt.Errorf("unable to enforce request.ext.prebid.data.eidpermissions because %v", err))
@@ -285,26 +273,41 @@ func getAuctionBidderRequests(auctionRequest AuctionRequest,
 	return bidderRequests, errs
 }
 
-func getBidderParamsForBidder(bidderParamsInReqExt map[string]map[string]json.RawMessage, bidder string) (json.RawMessage, error) {
-	var params json.RawMessage
-	if bidderParams, ok := bidderParamsInReqExt[bidder]; ok {
-		var err error
-		params, err = json.Marshal(bidderParams)
-		if err != nil {
-			return nil, err
-		}
+func buildRequestExtForBidder(bidder string, requestExt json.RawMessage, requestExtParsed *openrtb_ext.ExtRequest, bidderParamsInReqExt map[string]json.RawMessage) (json.RawMessage, error) {
+	if len(requestExt) == 0 || requestExtParsed == nil {
+		return json.RawMessage(``), nil
 	}
-	return params, nil
-}
 
-func getExtJson(req *openrtb2.BidRequest, unpackedExt *openrtb_ext.ExtRequest) (json.RawMessage, error) {
-	if len(req.Ext) == 0 || unpackedExt == nil {
-		return json.RawMessage(``), nil
+	// Resolve Bidder Params
+	var bidderParams json.RawMessage
+	if bidderParamsInReqExt != nil {
+		bidderParams = bidderParamsInReqExt[bidder]
+	}
+
+	// Copy Allowed Fields
+	// Per: https://docs.prebid.org/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#prebid-server-ortb2-extension-summary
+	prebid := openrtb_ext.ExtRequestPrebid{
+		Integration:         requestExtParsed.Prebid.Integration,
+		Channel:             requestExtParsed.Prebid.Channel,
+		Debug:               requestExtParsed.Prebid.Debug,
+		CurrencyConversions: requestExtParsed.Prebid.CurrencyConversions,
+		BidderParams:        bidderParams,
+	}
+
+	// Marshal New Prebid Object
+	prebidJson, err := json.Marshal(prebid)
+	if err != nil {
+		return nil, err
 	}
 
-	extCopy := *unpackedExt
-	extCopy.Prebid.SChains = nil
-	return json.Marshal(extCopy)
+	// Update Ext With Prebid Json
+	extMap := make(map[string]json.RawMessage)
+	if err := json.Unmarshal(requestExt, &extMap); err != nil {
+		return nil, err
+	}
+	extMap["prebid"] = prebidJson
+
+	return json.Marshal(extMap)
 }
 
 // extractBuyerUIDs parses the values from user.ext.prebid.buyeruids, and then deletes those values from the ext.
@@ -396,17 +399,28 @@ func splitImps(imps []openrtb2.Imp) (map[string][]openrtb2.Imp, error) {
 }
 
 func createSanitizedImpExt(impExt, impExtPrebid map[string]json.RawMessage) (map[string]json.RawMessage, error) {
-	sanitizedImpExt := make(map[string]json.RawMessage, 3)
+	sanitizedImpExt := make(map[string]json.RawMessage, 6)
+	sanitizedImpPrebidExt := make(map[string]json.RawMessage, 2)
+
+	// copy allowed imp[].ext.prebid fields
+	if v, exists := impExtPrebid["is_rewarded_inventory"]; exists {
+		sanitizedImpPrebidExt["is_rewarded_inventory"] = v
+	}
+
+	if v, exists := impExtPrebid["options"]; exists {
+		sanitizedImpPrebidExt["options"] = v
+	}
 
-	delete(impExtPrebid, openrtb_ext.PrebidExtBidderKey)
-	if len(impExtPrebid) > 0 {
-		if impExtPrebidJSON, err := json.Marshal(impExtPrebid); err == nil {
+	// marshal sanitized imp[].ext.prebid
+	if len(sanitizedImpPrebidExt) > 0 {
+		if impExtPrebidJSON, err := json.Marshal(sanitizedImpPrebidExt); err == nil {
 			sanitizedImpExt[openrtb_ext.PrebidExtKey] = impExtPrebidJSON
 		} else {
 			return nil, fmt.Errorf("cannot marshal ext.prebid: %v", err)
 		}
 	}
 
+	// copy reserved imp[].ext fields known to not be bidder names
 	if v, exists := impExt[openrtb_ext.FirstPartyDataExtKey]; exists {
 		sanitizedImpExt[openrtb_ext.FirstPartyDataExtKey] = v
 	}
@@ -647,7 +661,7 @@ func extractBidRequestExt(bidRequest *openrtb2.BidRequest) (*openrtb_ext.ExtRequ
 	requestExt := &openrtb_ext.ExtRequest{}
 
 	if bidRequest == nil {
-		return requestExt, fmt.Errorf("Error bidRequest should not be nil")
+		return requestExt, errors.New("Error bidRequest should not be nil")
 	}
 
 	if len(bidRequest.Ext) > 0 {
diff --git a/experiment/adscert/SignerLogger.go b/experiment/adscert/SignerLogger.go
new file mode 100644
index 00000000..1d99bcc6
--- /dev/null
+++ b/experiment/adscert/SignerLogger.go
@@ -0,0 +1,38 @@
+package adscert
+
+import (
+	"fmt"
+	"github.com/golang/glog"
+)
+
+type SignerLogger struct {
+}
+
+func (sl *SignerLogger) Debugf(format string, args ...interface{}) {
+	//there is no Debug level in glog
+	glog.Infof(format, args...)
+}
+
+func (sl *SignerLogger) Infof(format string, args ...interface{}) {
+	glog.Infof(format, args...)
+}
+
+func (sl *SignerLogger) Info(format string) {
+	glog.Info(format)
+}
+
+func (sl *SignerLogger) Warningf(format string, args ...interface{}) {
+	glog.Warningf(format, args...)
+}
+
+func (sl *SignerLogger) Errorf(format string, args ...interface{}) {
+	glog.Errorf(format, args...)
+}
+
+func (sl *SignerLogger) Fatalf(format string, args ...interface{}) {
+	glog.Fatalf(format, args...)
+}
+
+func (sl *SignerLogger) Panicf(format string, args ...interface{}) {
+	panic(fmt.Sprintf(format, args...))
+}
diff --git a/experiment/adscert/signer.go b/experiment/adscert/signer.go
index 352aa004..08b3f655 100644
--- a/experiment/adscert/signer.go
+++ b/experiment/adscert/signer.go
@@ -3,6 +3,7 @@ package adscert
 import (
 	"fmt"
 	"github.com/IABTechLab/adscert/pkg/adscert/api"
+	"github.com/IABTechLab/adscert/pkg/adscert/logger"
 	"github.com/IABTechLab/adscert/pkg/adscert/signatory"
 	"github.com/prebid/prebid-server/config"
 )
@@ -22,6 +23,7 @@ func (ns *NilSigner) Sign(destinationURL string, body []byte) (string, error) {
 }
 
 func NewAdCertsSigner(experimentAdCertsConfig config.ExperimentAdsCert) (Signer, error) {
+	logger.SetLoggerImpl(&SignerLogger{})
 	if experimentAdCertsConfig.Mode == config.AdCertsSignerModeInprocess {
 		return newInProcessSigner(experimentAdCertsConfig.InProcess)
 	}
diff --git a/metrics/metrics.go b/metrics/metrics.go
index 5c6493cb..31bfb15f 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -315,6 +315,8 @@ func CookieSyncStatuses() []CookieSyncStatus {
 		CookieSyncBadRequest,
 		CookieSyncOptOut,
 		CookieSyncGDPRHostCookieBlocked,
+		CookieSyncAccountBlocked,
+		CookieSyncAccountInvalid,
 	}
 }
 
@@ -347,6 +349,8 @@ const (
 	SetUidBadRequest            SetUidStatus = "bad_request"
 	SetUidOptOut                SetUidStatus = "opt_out"
 	SetUidGDPRHostCookieBlocked SetUidStatus = "gdpr_blocked_host_cookie"
+	SetUidAccountBlocked        SetUidStatus = "acct_blocked"
+	SetUidAccountInvalid        SetUidStatus = "acct_invalid"
 	SetUidSyncerUnknown         SetUidStatus = "syncer_unknown"
 )
 
@@ -357,6 +361,8 @@ func SetUidStatuses() []SetUidStatus {
 		SetUidBadRequest,
 		SetUidOptOut,
 		SetUidGDPRHostCookieBlocked,
+		SetUidAccountBlocked,
+		SetUidAccountInvalid,
 		SetUidSyncerUnknown,
 	}
 }
diff --git a/openrtb_ext/bid.go b/openrtb_ext/bid.go
index b0cacf85..61c720fe 100644
--- a/openrtb_ext/bid.go
+++ b/openrtb_ext/bid.go
@@ -23,6 +23,7 @@ type ExtBidPrebid struct {
 	Video             *ExtBidPrebidVideo  `json:"video,omitempty"`
 	Events            *ExtBidPrebidEvents `json:"events,omitempty"`
 	BidId             string              `json:"bidid,omitempty"`
+	Passthrough       json.RawMessage     `json:"passthrough,omitempty"`
 }
 
 // ExtBidPrebidCache defines the contract for  bidresponse.seatbid.bid[i].ext.prebid.cache
@@ -173,4 +174,5 @@ const (
 	StoredRequestAttributes = "storedrequestattributes"
 	OriginalBidCpmKey       = "origbidcpm"
 	OriginalBidCurKey       = "origbidcur"
+	Passthrough             = "passthrough"
 )
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 0ed3d678..f9c93bf6 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -99,7 +99,9 @@ const (
 	BidderAdot              BidderName = "adot"
 	BidderAdpone            BidderName = "adpone"
 	BidderAdprime           BidderName = "adprime"
+	BidderAdrino            BidderName = "adrino"
 	BidderAdtarget          BidderName = "adtarget"
+	BidderAdtrgtme          BidderName = "adtrgtme"
 	BidderAdtelligent       BidderName = "adtelligent"
 	BidderAdvangelists      BidderName = "advangelists"
 	BidderAdView            BidderName = "adview"
@@ -258,7 +260,9 @@ func CoreBidderNames() []BidderName {
 		BidderAdot,
 		BidderAdpone,
 		BidderAdprime,
+		BidderAdrino,
 		BidderAdtarget,
+		BidderAdtrgtme,
 		BidderAdtelligent,
 		BidderAdvangelists,
 		BidderAdView,
diff --git a/openrtb_ext/imp.go b/openrtb_ext/imp.go
index bef6cd65..ae151435 100644
--- a/openrtb_ext/imp.go
+++ b/openrtb_ext/imp.go
@@ -22,6 +22,8 @@ type ExtImpPrebid struct {
 	Bidder map[string]json.RawMessage `json:"bidder"`
 
 	Options *Options `json:"options,omitempty"`
+
+	Passthrough json.RawMessage `json:"passthrough,omitempty"`
 }
 
 // ExtStoredRequest defines the contract for bidrequest.imp[i].ext.prebid.storedrequest
diff --git a/openrtb_ext/imp_adrino.go b/openrtb_ext/imp_adrino.go
new file mode 100644
index 00000000..7c5c53b2
--- /dev/null
+++ b/openrtb_ext/imp_adrino.go
@@ -0,0 +1,5 @@
+package openrtb_ext
+
+type ExtImpAdrino struct {
+	Hash string `json:"hash"`
+}
diff --git a/openrtb_ext/imp_adtrgtme.go b/openrtb_ext/imp_adtrgtme.go
new file mode 100644
index 00000000..f44daae1
--- /dev/null
+++ b/openrtb_ext/imp_adtrgtme.go
@@ -0,0 +1,4 @@
+package openrtb_ext
+
+// ExtImpAdtrgtme defines the contract for bidrequest.imp[i].ext.adtrgtme
+type ExtImpAdtrgtme struct{}
diff --git a/openrtb_ext/imp_deepintent.go b/openrtb_ext/imp_deepintent.go
index 34c537d4..b50c8fe0 100644
--- a/openrtb_ext/imp_deepintent.go
+++ b/openrtb_ext/imp_deepintent.go
@@ -1,5 +1,5 @@
 package openrtb_ext
 
 type ExtImpDeepintent struct {
-	TagID string `json:tagId`
+	TagID string `json:"tagId"`
 }
diff --git a/openrtb_ext/request.go b/openrtb_ext/request.go
index 67cad55b..b3807c5d 100644
--- a/openrtb_ext/request.go
+++ b/openrtb_ext/request.go
@@ -38,26 +38,26 @@ type ExtRequestPrebid struct {
 	Aliases              map[string]string         `json:"aliases,omitempty"`
 	AliasGVLIDs          map[string]uint16         `json:"aliasgvlids,omitempty"`
 	BidAdjustmentFactors map[string]float64        `json:"bidadjustmentfactors,omitempty"`
+	BidderConfigs        []BidderConfig            `json:"bidderconfig,omitempty"`
+	BidderParams         json.RawMessage           `json:"bidderparams,omitempty"`
 	Cache                *ExtRequestPrebidCache    `json:"cache,omitempty"`
 	Channel              *ExtRequestPrebidChannel  `json:"channel,omitempty"`
+	CurrencyConversions  *ExtRequestCurrency       `json:"currency,omitempty"`
 	Data                 *ExtRequestPrebidData     `json:"data,omitempty"`
 	Debug                bool                      `json:"debug,omitempty"`
-	Integration          string                    `json:"integration,omitempty"`
 	Events               json.RawMessage           `json:"events,omitempty"`
+	Experiment           *Experiment               `json:"experiment,omitempty"`
+	Integration          string                    `json:"integration,omitempty"`
+	Passthrough          json.RawMessage           `json:"passthrough,omitempty"`
 	SChains              []*ExtRequestPrebidSChain `json:"schains,omitempty"`
 	StoredRequest        *ExtStoredRequest         `json:"storedrequest,omitempty"`
 	SupportDeals         bool                      `json:"supportdeals,omitempty"`
 	Targeting            *ExtRequestTargeting      `json:"targeting,omitempty"`
-	BidderParams         json.RawMessage           `json:"bidderparams,omitempty"`
 
 	// NoSale specifies bidders with whom the publisher has a legal relationship where the
 	// passing of personally identifiable information doesn't constitute a sale per CCPA law.
 	// The array may contain a single sstar ('*') entry to represent all bidders.
 	NoSale []string `json:"nosale,omitempty"`
-
-	CurrencyConversions *ExtRequestCurrency `json:"currency,omitempty"`
-	BidderConfigs       []BidderConfig      `json:"bidderconfig,omitempty"`
-	Experiment          *Experiment         `json:"experiment,omitempty"`
 }
 
 // Experiment defines if experimental features are available for the request
diff --git a/openrtb_ext/response.go b/openrtb_ext/response.go
index 044bc0bd..b20e741c 100644
--- a/openrtb_ext/response.go
+++ b/openrtb_ext/response.go
@@ -39,7 +39,8 @@ type ExtResponseSyncData struct {
 
 // ExtResponsePrebid defines the contract for bidresponse.ext.prebid
 type ExtResponsePrebid struct {
-	AuctionTimestamp int64 `json:"auctiontimestamp,omitempty"`
+	AuctionTimestamp int64           `json:"auctiontimestamp,omitempty"`
+	Passthrough      json.RawMessage `json:"passthrough,omitempty"`
 }
 
 // ExtUserSync defines the contract for bidresponse.ext.usersync.{bidder}.syncs[i]
diff --git a/schain/schainwriter.go b/schain/schainwriter.go
index 37d7b631..dbbd91ba 100644
--- a/schain/schainwriter.go
+++ b/schain/schainwriter.go
@@ -79,11 +79,5 @@ func (w SChainWriter) Write(req *openrtb2.BidRequest, bidder string) {
 
 // extPrebidSChainExists checks if an schain exists in the ORTB 2.5 req.ext.prebid.schain location
 func extPrebidSChainExists(reqExt *openrtb_ext.ExtRequest) bool {
-	if reqExt == nil {
-		return false
-	}
-	if reqExt.Prebid.SChains == nil {
-		return false
-	}
-	return true
+	return reqExt != nil && reqExt.Prebid.SChains != nil
 }
diff --git a/static/bidder-info/adrino.yaml b/static/bidder-info/adrino.yaml
new file mode 100644
index 00000000..24bdfb37
--- /dev/null
+++ b/static/bidder-info/adrino.yaml
@@ -0,0 +1,7 @@
+maintainer:
+  email: dev@adrino.pl
+gvlVendorID: 1072
+capabilities:
+  site:
+    mediaTypes:
+      - native
diff --git a/static/bidder-info/adtrgtme.yaml b/static/bidder-info/adtrgtme.yaml
new file mode 100644
index 00000000..69deda5b
--- /dev/null
+++ b/static/bidder-info/adtrgtme.yaml
@@ -0,0 +1,9 @@
+maintainer:
+  email: "info@adtarget.me"
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+  site:
+    mediaTypes:
+      - banner
\ No newline at end of file
diff --git a/static/bidder-info/ix.yaml b/static/bidder-info/ix.yaml
index 8c46525c..1efa8af0 100644
--- a/static/bidder-info/ix.yaml
+++ b/static/bidder-info/ix.yaml
@@ -18,4 +18,6 @@ userSync:
   redirect:
     url: "https://ssum.casalemedia.com/usermatchredir?s=194962&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}"
     userMacro: ""
+  iframe:
+    url: "https://ssum-sec.casalemedia.com/usermatch?s=184674&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}"
     # ix appends the user id to end of the redirect url and does not utilize a macro
diff --git a/static/bidder-info/pubmatic.yaml b/static/bidder-info/pubmatic.yaml
index 1688e639..085acfdb 100644
--- a/static/bidder-info/pubmatic.yaml
+++ b/static/bidder-info/pubmatic.yaml
@@ -6,10 +6,12 @@ capabilities:
     mediaTypes:
       - banner
       - video
+      - native
   site:
     mediaTypes:
       - banner
       - video
+      - native
 userSync:
   iframe:
     url: "https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&predirect={{.RedirectURL}}"
diff --git a/static/bidder-info/richaudience.yaml b/static/bidder-info/richaudience.yaml
index 3e45dc0b..3ec74ccd 100644
--- a/static/bidder-info/richaudience.yaml
+++ b/static/bidder-info/richaudience.yaml
@@ -15,3 +15,6 @@ userSync:
   iframe:
     url: "https://sync.richaudience.com/74889303289e27f327ad0c6de7be7264/?consentString={{.GDPRConsent}}&r={{.RedirectURL}}"
     userMacro: "[PDID]"
+  redirect:
+      url: "https://sync.richaudience.com/f7872c90c5d3791e2b51f7edce1a0a5d/?p=pbs&consentString={{.GDPRConsent}}&r={{.RedirectURL}}"
+      userMacro: "[PDID]"
diff --git a/static/bidder-params/adrino.json b/static/bidder-params/adrino.json
new file mode 100644
index 00000000..56f7404c
--- /dev/null
+++ b/static/bidder-params/adrino.json
@@ -0,0 +1,16 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "Adrino Adapter Params",
+    "description": "A schema which validates params accepted by the Adrino adapter",
+    "type": "object",
+    "properties": {
+        "hash": {
+            "type": "string",
+            "minLength": 1,
+            "description": "The placement id provided by Adrino."
+        }
+    },
+    "required": [
+        "hash"
+    ]
+}
diff --git a/static/bidder-params/adtrgtme.json b/static/bidder-params/adtrgtme.json
new file mode 100644
index 00000000..e0da860c
--- /dev/null
+++ b/static/bidder-params/adtrgtme.json
@@ -0,0 +1,8 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Adtrgtme adapter params",
+  "description": "A schema which validates params accepted by the Adtrgtme adapter",
+  "type": "object",
+
+  "properties": {}
+}
\ No newline at end of file


Test patch:
diff --git a/adapters/adrino/adrino_test.go b/adapters/adrino/adrino_test.go
new file mode 100644
index 00000000..a7c19d02
--- /dev/null
+++ b/adapters/adrino/adrino_test.go
@@ -0,0 +1,28 @@
+package adrino
+
+import (
+	"github.com/stretchr/testify/assert"
+	"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.BidderAdrino, config.Adapter{
+		Endpoint: "https://prd-prebid-bidder.adrino.io/openrtb/bid"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "adrinotest", bidder)
+}
+
+func TestEndpointTemplateMalformed(t *testing.T) {
+	_, buildErr := Builder(openrtb_ext.BidderAdrino, config.Adapter{
+		Endpoint: "{{Malformed}}"})
+
+	assert.Nil(t, buildErr)
+}
diff --git a/adapters/adrino/adrinotest/exemplary/no-bid.json b/adapters/adrino/adrinotest/exemplary/no-bid.json
new file mode 100644
index 00000000..66b64e14
--- /dev/null
+++ b/adapters/adrino/adrinotest/exemplary/no-bid.json
@@ -0,0 +1,73 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "ext": {
+                    "bidder": {
+                        "hash": "123456"
+                    }
+                },
+                "native": {
+                    "request": "{json string}",
+                    "ver": "1.2"
+                }
+            }
+        ],
+        "site": {
+            "publisher": {
+                "id": "1"
+            },
+            "page": "some-page-url"
+        },
+        "device": {
+            "w": 1920,
+            "h": 800
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://prd-prebid-bidder.adrino.io/openrtb/bid",
+                "headers": {
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                },
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "ext": {
+                                "bidder": {
+                                    "hash": "123456"
+                                }
+                            },
+                            "native": {
+                                "request": "{json string}",
+                                "ver": "1.2"
+                            }
+                        }
+                    ],
+                    "site": {
+                        "publisher": {
+                            "id": "1"
+                        },
+                        "page": "some-page-url"
+                    },
+                    "device": {
+                        "w": 1920,
+                        "h": 800
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 204,
+                "body": {}
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
diff --git a/adapters/adrino/adrinotest/exemplary/single-native.json b/adapters/adrino/adrinotest/exemplary/single-native.json
new file mode 100644
index 00000000..41e4b5ef
--- /dev/null
+++ b/adapters/adrino/adrinotest/exemplary/single-native.json
@@ -0,0 +1,115 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "ext": {
+                    "bidder": {
+                        "hash": "123456"
+                    }
+                },
+                "native": {
+                    "request": "{json string}",
+                    "ver": "1.2"
+                }
+            }
+        ],
+        "site": {
+            "publisher": {
+                "id": "1"
+            },
+            "page": "some-page-url"
+        },
+        "device": {
+            "w": 1920,
+            "h": 800
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://prd-prebid-bidder.adrino.io/openrtb/bid",
+                "headers": {
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                },
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "ext": {
+                                "bidder": {
+                                    "hash": "123456"
+                                }
+                            },
+                            "native": {
+                                "request": "{json string}",
+                                "ver": "1.2"
+                            }
+                        }
+                    ],
+                    "site": {
+                        "publisher": {
+                            "id": "1"
+                        },
+                        "page": "some-page-url"
+                    },
+                    "device": {
+                        "w": 1920,
+                        "h": 800
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "test-imp-id",
+                                    "price": 10,
+                                    "adm": "{json response string}",
+                                    "crid": "test-creative-id",
+                                    "ext": {
+                                        "prebid": {
+                                            "type": "native"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "cur": "PLN"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "PLN",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "test-imp-id",
+                        "price": 10,
+                        "adm": "{json response string}",
+                        "crid": "test-creative-id",
+                        "ext": {
+                            "prebid": {
+                                "type": "native"
+                            }
+                        }
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/adrino/adrinotest/supplemental/unknown-hash.json b/adapters/adrino/adrinotest/supplemental/unknown-hash.json
new file mode 100644
index 00000000..e678b526
--- /dev/null
+++ b/adapters/adrino/adrinotest/supplemental/unknown-hash.json
@@ -0,0 +1,73 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "ext": {
+                    "bidder": {
+                        "hash": "some-unknown-hash"
+                    }
+                },
+                "native": {
+                    "request": "{json string}",
+                    "ver": "1.2"
+                }
+            }
+        ],
+        "site": {
+            "publisher": {
+                "id": "1"
+            },
+            "page": "some-page-url"
+        },
+        "device": {
+            "w": 1920,
+            "h": 800
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://prd-prebid-bidder.adrino.io/openrtb/bid",
+                "headers": {
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                },
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "ext": {
+                                "bidder": {
+                                    "hash": "some-unknown-hash"
+                                }
+                            },
+                            "native": {
+                                "request": "{json string}",
+                                "ver": "1.2"
+                            }
+                        }
+                    ],
+                    "site": {
+                        "publisher": {
+                            "id": "1"
+                        },
+                        "page": "some-page-url"
+                    },
+                    "device": {
+                        "w": 1920,
+                        "h": 800
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 204,
+                "body": {}
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
diff --git a/adapters/adrino/params_test.go b/adapters/adrino/params_test.go
new file mode 100644
index 00000000..f82f08ce
--- /dev/null
+++ b/adapters/adrino/params_test.go
@@ -0,0 +1,51 @@
+package adrino
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// This file actually intends to test static/bidder-params/adrino.json
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderAdrino, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected adrino params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderAdrino, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"hash":"abc123"}`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"hash":""}`,
+	`{"aid":123, "placementId":"123", "siteId":"321"}`,
+}
diff --git a/adapters/adtrgtme/adtrgtme_test.go b/adapters/adtrgtme/adtrgtme_test.go
new file mode 100644
index 00000000..e3f87c20
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtme_test.go
@@ -0,0 +1,20 @@
+package adtrgtme
+
+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.BidderAdtrgtme, config.Adapter{
+		Endpoint: "http://localhost/ssp"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "adtrgtmetest", bidder)
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/exemplary/banner-app.json b/adapters/adtrgtme/adtrgtmetest/exemplary/banner-app.json
new file mode 100644
index 00000000..406c1863
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/exemplary/banner-app.json
@@ -0,0 +1,146 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "app": {
+      "publisher": {
+        "id": "test-site-publisher-id"
+      },
+      "cat": [
+        "test-cat"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "domain": "testapp.com",
+      "id": "123456789"
+    },
+    "device": {
+      "ua": "test-device-user-agent",
+      "ip": "123.123.123.123",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-device-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "body": {
+          "id": "test-req-id",
+          "at": 1,
+          "tmax": 300,
+          "imp": [
+            {
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "id": "test-bid-id",
+              "bidfloor": 1,
+              "bidfloorcur": "USD",
+              "secure": 1
+            }
+          ],
+          "app": {
+            "publisher": {
+              "id": "test-site-publisher-id"
+            },
+            "cat": [
+              "test-cat"
+            ],
+            "bundle": "com.app.test",
+            "name": "Test App",
+            "domain": "testapp.com",
+            "id": "123456789"
+          },
+          "device": {
+            "ua": "test-device-user-agent",
+            "ip": "123.123.123.123",
+            "geo": {
+              "country": "TST"
+            },
+            "os": "Android",
+            "language": "en"
+          },
+          "user": {
+            "id": "test-user-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-req-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-bid-id",
+                  "impid": "test-bid-id",
+                  "price": 1,
+                  "adm": "<div>test</div>",
+                  "crid": "test-creative-id"
+                }
+              ]
+            }
+          ],
+          "bidid": "test-seatbid-id",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test-bid-id",
+            "impid": "test-bid-id",
+            "price": 1,
+            "adm": "<div>test</div>",
+            "crid": "test-creative-id"
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/exemplary/banner-web.json b/adapters/adtrgtme/adtrgtmetest/exemplary/banner-web.json
new file mode 100644
index 00000000..44f14aac
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/exemplary/banner-web.json
@@ -0,0 +1,142 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "site": {
+      "id": "123456789",
+      "cat": [
+        "test-cat"
+      ],
+      "page": "test-page-site",
+      "publisher": {
+        "id": "test-site-publisher-id"
+      }
+    },
+    "device": {
+      "ua": "test-device-user-agent",
+      "ip": "123.123.123.123",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-device-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "body": {
+          "id": "test-req-id",
+          "at": 1,
+          "tmax": 300,
+          "imp": [
+            {
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "id": "test-bid-id",
+              "bidfloor": 1,
+              "bidfloorcur": "USD",
+              "secure": 1
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "cat": [
+              "test-cat"
+            ],
+            "page": "test-page-site",
+            "publisher": {
+              "id": "test-site-publisher-id"
+            }
+          },
+          "device": {
+            "ua": "test-device-user-agent",
+            "ip": "123.123.123.123",
+            "geo": {
+              "country": "TST"
+            },
+            "os": "Android",
+            "language": "en"
+          },
+          "user": {
+            "id": "test-user-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-req-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-bid-id",
+                  "impid": "test-bid-id",
+                  "price": 1,
+                  "adm": "<div>test</div>",
+                  "crid": "test-creative-id"
+                }
+              ]
+            }
+          ],
+          "bidid": "test-seatbid-id",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test-bid-id",
+            "impid": "test-bid-id",
+            "price": 1,
+            "adm": "<div>test</div>",
+            "crid": "test-creative-id"
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/banner-app-headers-ipv6.json b/adapters/adtrgtme/adtrgtmetest/supplemental/banner-app-headers-ipv6.json
new file mode 100644
index 00000000..7537a902
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/banner-app-headers-ipv6.json
@@ -0,0 +1,146 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "app": {
+      "publisher": {
+        "id": "test-site-publisher-id"
+      },
+      "cat": [
+        "test-cat"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "domain": "testapp.com",
+      "id": "123456789"
+    },
+    "device": {
+      "ua": "test-device-user-agent",
+      "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-device-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
+          ]
+        },
+        "body": {
+          "id": "test-req-id",
+          "at": 1,
+          "tmax": 300,
+          "imp": [
+            {
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "id": "test-bid-id",
+              "bidfloor": 1,
+              "bidfloorcur": "USD",
+              "secure": 1
+            }
+          ],
+          "app": {
+            "publisher": {
+              "id": "test-site-publisher-id"
+            },
+            "cat": [
+              "test-cat"
+            ],
+            "bundle": "com.app.test",
+            "name": "Test App",
+            "domain": "testapp.com",
+            "id": "123456789"
+          },
+          "device": {
+            "ua": "test-device-user-agent",
+            "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+            "geo": {
+              "country": "TST"
+            },
+            "os": "Android",
+            "language": "en"
+          },
+          "user": {
+            "id": "test-user-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-req-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-bid-id",
+                  "impid": "test-bid-id",
+                  "price": 1,
+                  "adm": "<div>test</div>",
+                  "crid": "test-creative-id"
+                }
+              ]
+            }
+          ],
+          "bidid": "test-seatbid-id",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test-bid-id",
+            "impid": "test-bid-id",
+            "price": 1,
+            "adm": "<div>test</div>",
+            "crid": "test-creative-id"
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/banner-web-headers-ipv6.json b/adapters/adtrgtme/adtrgtmetest/supplemental/banner-web-headers-ipv6.json
new file mode 100644
index 00000000..3ad7cf11
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/banner-web-headers-ipv6.json
@@ -0,0 +1,142 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "site": {
+      "id": "123456789",
+      "cat": [
+        "test-cat"
+      ],
+      "page": "test-page-site",
+      "publisher": {
+        "id": "test-site-publisher-id"
+      }
+    },
+    "device": {
+      "ua": "test-device-user-agent",
+      "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-device-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
+          ]
+        },
+        "body": {
+          "id": "test-req-id",
+          "at": 1,
+          "tmax": 300,
+          "imp": [
+            {
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "id": "test-bid-id",
+              "bidfloor": 1,
+              "bidfloorcur": "USD",
+              "secure": 1
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "cat": [
+              "test-cat"
+            ],
+            "page": "test-page-site",
+            "publisher": {
+              "id": "test-site-publisher-id"
+            }
+          },
+          "device": {
+            "ua": "test-device-user-agent",
+            "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+            "geo": {
+              "country": "TST"
+            },
+            "os": "Android",
+            "language": "en"
+          },
+          "user": {
+            "id": "test-user-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-req-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-bid-id",
+                  "impid": "test-bid-id",
+                  "price": 1,
+                  "adm": "<div>test</div>",
+                  "crid": "test-creative-id"
+                }
+              ]
+            }
+          ],
+          "bidid": "test-seatbid-id",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test-bid-id",
+            "impid": "test-bid-id",
+            "price": 1,
+            "adm": "<div>test</div>",
+            "crid": "test-creative-id"
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/empty-seatbid-array.json b/adapters/adtrgtme/adtrgtmetest/supplemental/empty-seatbid-array.json
new file mode 100644
index 00000000..0f2b55be
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/empty-seatbid-array.json
@@ -0,0 +1,125 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-buyer-id"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "test-cat"
+      ],
+      "bundle": "com.app.test",
+      "name": "test-app",
+      "domain": "test-app.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-test",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "test-adtarget-test"
+            }
+          ],
+          "app": {
+            "id": "123456789",
+            "name": "test-app",
+            "bundle": "com.app.test",
+            "domain": "test-app.com",
+            "cat": [
+              "test-cat"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-buyer-id"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-resp-id",
+          "seatbid": [
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "mockResponse": {
+    "status": 200,
+    "body": "invalid response"
+  },
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Empty SeatBid array",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/invalid-response.json b/adapters/adtrgtme/adtrgtmetest/supplemental/invalid-response.json
new file mode 100644
index 00000000..b25ff67d
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/invalid-response.json
@@ -0,0 +1,106 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-buyer-id"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "test-app",
+      "domain": "test-app.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-test",
+        "banner": {
+          "w": 320,
+          "h": 50
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "w": 320,
+                "h": 50
+              },
+              "tagid": "test-adtarget-test"
+            }
+          ],
+          "app": {
+            "id": "123456789",
+            "name": "test-app",
+            "bundle": "com.app.test",
+            "domain": "test-app.com",
+            "cat": [
+              "IAB22-1"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-buyer-id"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": "invalid response"
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad Server Response",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/not-found-imp.json b/adapters/adtrgtme/adtrgtmetest/supplemental/not-found-imp.json
new file mode 100644
index 00000000..8ca9a407
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/not-found-imp.json
@@ -0,0 +1,128 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user-id"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-unsupported-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "test-unsupported-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user-id"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-imp-id",
+                  "impid": "test-not-found-imp-id",
+                  "price": 3.5,
+                  "adm": "test-imp-mrkp",
+                  "adomain": [
+                    "mock-site.com"
+                  ],
+                  "crid": "20",
+                  "w": 1280,
+                  "h": 720
+                }
+              ],
+              "seat": "aceex"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Failed to find impression: \"test-not-found-imp-id\"",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-app-id.json b/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-app-id.json
new file mode 100644
index 00000000..49c7924a
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-app-id.json
@@ -0,0 +1,48 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "device": {
+      "ua": "test-device-user-agent",
+      "ip": "123.123.123.123",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "app": {
+      "publisher": {
+        "id": "test-site-publisher-id"
+      },
+      "cat": [
+        "test-cat"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "domain": "testapp.com"
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "request.App.ID is not provided",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-site-id.json b/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-site-id.json
new file mode 100644
index 00000000..bb38d8ef
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-site-id.json
@@ -0,0 +1,46 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "device": {
+      "ua": "test-device-user-agent",
+      "ip": "123.123.123.123",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "site": {
+      "cat": [
+        "test-cat"
+      ],
+      "page": "test-page-site",
+      "publisher": {
+        "id": "test-site-publisher-id"
+      }
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "request.Site.ID is not provided",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-site-or-app.json b/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-site-or-app.json
new file mode 100644
index 00000000..b4320e17
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/not-provided-site-or-app.json
@@ -0,0 +1,37 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "at": 1,
+    "tmax": 300,
+    "imp": [
+      {
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "id": "test-bid-id",
+        "bidfloor": 1,
+        "bidfloorcur": "USD",
+        "secure": 1
+      }
+    ],
+    "device": {
+      "ua": "test-device-user-agent",
+      "ip": "123.123.123.123",
+      "geo": {
+        "country": "TST"
+      },
+      "os": "Android",
+      "language": "en"
+    },
+    "user": {
+      "id": "test-user-id"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "request.Site or request.App are not provided",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-bad-request.json b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-bad-request.json
new file mode 100644
index 00000000..2aab35e5
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-bad-request.json
@@ -0,0 +1,87 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "test-app",
+      "domain": "test-app.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "test-adtarget-tag-id"
+            }
+          ],
+          "app": {
+            "publisher": {
+              "id": "123456789"
+            },
+            "cat": [
+              "IAB22-1"
+            ],
+            "bundle": "com.app.test",
+            "name": "test-app",
+            "domain": "test-app.com",
+            "id": "123456789"
+          },
+          "user": {
+            "buyeruid": "test-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 400
+      }
+    }
+  ],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: [ 400 ]",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-internal-server-error.json b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-internal-server-error.json
new file mode 100644
index 00000000..ed8348f8
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-internal-server-error.json
@@ -0,0 +1,77 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 500
+      }
+    }
+  ],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: [ 500 ]. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-no-content.json b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-no-content.json
new file mode 100644
index 00000000..ba886cf3
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-no-content.json
@@ -0,0 +1,72 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 204
+      }
+    }
+  ],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": []
+}
\ No newline at end of file
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-service-unavaliable.json b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-service-unavaliable.json
new file mode 100644
index 00000000..69911727
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-service-unavaliable.json
@@ -0,0 +1,77 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 503
+      }
+    }
+  ],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Something went wrong, please contact your Account Manager. Status Code: [ 503 ] ",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-temporary-redirect.json b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-temporary-redirect.json
new file mode 100644
index 00000000..159de604
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/status-code-temporary-redirect.json
@@ -0,0 +1,77 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 307
+      }
+    }
+  ],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: [ 307 ]. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/unsupported-bid-type-native.json b/adapters/adtrgtme/adtrgtmetest/supplemental/unsupported-bid-type-native.json
new file mode 100644
index 00000000..e7765809
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/unsupported-bid-type-native.json
@@ -0,0 +1,118 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user-id"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-unsupported-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "native": {
+          "ver": "1.1",
+          "request": "{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "test-unsupported-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "native": {
+                "ver": "1.1",
+                "request": "{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user-id"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-imp-id",
+                  "impid": "test-unsupported-imp-id",
+                  "price": 3.5,
+                  "adm": "test-imp-mrkp",
+                  "adomain": [
+                    "mock-site.com"
+                  ],
+                  "crid": "20",
+                  "w": 1280,
+                  "h": 720
+                }
+              ],
+              "seat": "aceex"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unsupported bidtype for bid: \"test-unsupported-imp-id\"",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adtrgtme/adtrgtmetest/supplemental/unsupported-bid-type-video.json b/adapters/adtrgtme/adtrgtmetest/supplemental/unsupported-bid-type-video.json
new file mode 100644
index 00000000..2394806d
--- /dev/null
+++ b/adapters/adtrgtme/adtrgtmetest/supplemental/unsupported-bid-type-video.json
@@ -0,0 +1,128 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "test-user-id"
+    },
+    "site": {
+      "id": "123456789",
+      "page": "mock-site.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-unsupported-imp-id",
+        "tagid": "test-adtarget-tag-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://localhost/ssp?s=123456789&prebid",
+        "body": {
+          "id": "test-req-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "test-unsupported-imp-id",
+              "tagid": "test-adtarget-tag-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              }
+            }
+          ],
+          "site": {
+            "id": "123456789",
+            "page": "mock-site.com",
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "test-user-id"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test-imp-id",
+                  "impid": "test-unsupported-imp-id",
+                  "price": 3.5,
+                  "adm": "test-imp-mrkp",
+                  "adomain": [
+                    "mock-site.com"
+                  ],
+                  "crid": "20",
+                  "w": 1280,
+                  "h": 720
+                }
+              ],
+              "seat": "aceex"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unsupported bidtype for bid: \"test-unsupported-imp-id\"",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/pubmatic/pubmatictest/exemplary/native.json b/adapters/pubmatic/pubmatictest/exemplary/native.json
new file mode 100644
index 00000000..f299c251
--- /dev/null
+++ b/adapters/pubmatic/pubmatictest/exemplary/native.json
@@ -0,0 +1,116 @@
+{
+  "mockBidRequest": {
+      "id": "test-native-request",
+      "imp": [
+          {
+              "id": "test-native-imp",
+              "native": {
+                  "request": "{\"assets\":[{\"id\":1,\"img\":{\"ext\":{\"image1\":\"image2\"},\"h\": 250,\"mimes\":[\"image\/gif\",\"image\/png\"],\"type\":3,\"w\":300},\"required\":1}]}"
+              },
+              "ext": {
+                  "bidder": {
+                      "publisherId": "999",
+                      "wrapper": {
+                          "version": 1,
+                          "profile": 5123
+                      }
+                  }
+              }
+          }
+      ],
+      "ext": {
+        "prebid": {}
+      },
+      "device": {
+          "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
+      },
+      "site": {
+          "id": "siteID",
+          "publisher": {
+              "id": "1234"
+          }
+      }
+  },
+  "httpCalls": [
+      {
+          "expectedRequest": {
+              "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server",
+              "body": {
+                  "id": "test-native-request",
+                  "imp": [
+                      {
+                          "id": "test-native-imp",
+                          "native": {
+                              "request": "{\"assets\":[{\"id\":1,\"img\":{\"ext\":{\"image1\":\"image2\"},\"h\": 250,\"mimes\":[\"image\/gif\",\"image\/png\"],\"type\":3,\"w\":300},\"required\":1}]}"
+                          }
+                      }
+                  ],
+                  "device": {
+                      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
+                  },
+                  "site": {
+                      "id": "siteID",
+                      "publisher": {
+                          "id": "999"
+                      }
+                  },
+                  "ext": {
+                      "wrapper": {
+                          "profile": 5123,
+                          "version": 1
+                      }
+                  }
+              }
+          },
+          "mockResponse": {
+              "status": 200,
+              "body": {
+                  "id": "test-native-request",
+                  "seatbid": [
+                      {
+                          "seat": "958",
+                          "bid": [
+                              {
+                                  "id": "test-native-request",
+                                  "impid": "test-native-imp",
+                                  "price": 0.500000,
+                                  "adid": "some-test-id",
+                                  "adm": "{\"native\":{\"assets\":[{\"id\":2,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":4},{\"id\":3,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"id\":1,\"title\":{\"text\":\"Native Test Title\"}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":5}],\"imptrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"jstracker\":\"<script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'><script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'>\",\"link\":{\"clicktrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"fallback\":\"http://www.pubmatic.com\",\"url\":\"//www.pubmatic.com\"}}}",
+                                  "crid": "29681110",
+                                  "ext": {
+                                      "deal_channel": 1,
+                                      "bidtype": 2
+                                  }
+                              }
+                          ]
+                      }
+                  ],
+                  "bidid": "5778926625248726496",
+                  "cur": "USD"
+              }
+          }
+      }
+  ],
+  "expectedBidResponses": [
+      {
+          "currency": "USD",
+          "bids": [
+              {
+                  "bid": {
+                      "id": "test-native-request",
+                      "impid": "test-native-imp",
+                      "price": 0.5,
+                      "adid": "some-test-id",
+                      "adm": "{\"assets\":[{\"id\":2,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":4},{\"id\":3,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"id\":1,\"title\":{\"text\":\"Native Test Title\"}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":5}],\"imptrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"jstracker\":\"<script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'><script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'>\",\"link\":{\"clicktrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"fallback\":\"http://www.pubmatic.com\",\"url\":\"//www.pubmatic.com\"}}",
+                      "crid": "29681110",
+                      "ext": {
+                          "deal_channel": 1,
+                          "bidtype": 2
+                      }
+                  },
+                  "type": "native"
+              }
+          ]
+      }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/pubmatic/pubmatictest/supplemental/app.json b/adapters/pubmatic/pubmatictest/supplemental/app.json
index c6ed97a5..01ba1f2e 100644
--- a/adapters/pubmatic/pubmatictest/supplemental/app.json
+++ b/adapters/pubmatic/pubmatictest/supplemental/app.json
@@ -134,5 +134,11 @@
           }
         ]
       }
+    ],
+    "expectedMakeBidsErrors": [
+      {
+        "value": "unexpected end of JSON input",
+        "comparison": "literal"
+      }
     ]
   }
\ No newline at end of file
diff --git a/adapters/pubmatic/pubmatictest/supplemental/audio.json b/adapters/pubmatic/pubmatictest/supplemental/audio.json
index 2befa39d..4142e334 100644
--- a/adapters/pubmatic/pubmatictest/supplemental/audio.json
+++ b/adapters/pubmatic/pubmatictest/supplemental/audio.json
@@ -22,7 +22,7 @@
 
   "expectedMakeRequestsErrors": [
     {
-      "value": "Invalid MediaType. PubMatic only supports Banner and Video. Ignoring ImpID=unsupported-audio-imp",
+      "value": "invalid MediaType. PubMatic only supports Banner, Video and Native. Ignoring ImpID=unsupported-audio-imp",
       "comparison": "literal"
     }
   ]
diff --git a/config/accounts_test.go b/config/accounts_test.go
index edb6bed5..c4566329 100644
--- a/config/accounts_test.go
+++ b/config/accounts_test.go
@@ -771,7 +771,7 @@ func TestAlternateBidderCodes_IsValidBidderCode(t *testing.T) {
 			wantErr:     errors.New(`alternateBidderCodes not defined for adapter "pubmatic", rejecting bids for "groupm"`),
 		},
 		{
-			name: "account.alternatebiddercodes config enabled but adapter config has allowedBidderCodes list empty or not defined",
+			name: "account.alternatebiddercodes config enabled but adapter config is disabled",
 			args: args{
 				bidder:          "pubmatic",
 				alternateBidder: "groupm",
@@ -779,12 +779,26 @@ func TestAlternateBidderCodes_IsValidBidderCode(t *testing.T) {
 			fields: fields{
 				Enabled: true,
 				Bidders: map[string]AdapterAlternateBidderCodes{
-					"pubmatic": {},
+					"pubmatic": {Enabled: false},
 				},
 			},
 			wantIsValid: false,
 			wantErr:     errors.New(`alternateBidderCodes disabled for "pubmatic", rejecting bids for "groupm"`),
 		},
+		{
+			name: "account.alternatebiddercodes and adapter config enabled but adapter config does not have allowedBidderCodes defined",
+			args: args{
+				bidder:          "pubmatic",
+				alternateBidder: "groupm",
+			},
+			fields: fields{
+				Enabled: true,
+				Bidders: map[string]AdapterAlternateBidderCodes{
+					"pubmatic": {Enabled: true},
+				},
+			},
+			wantIsValid: true,
+		},
 		{
 			name: "allowedBidderCodes is *",
 			args: args{
@@ -795,6 +809,7 @@ func TestAlternateBidderCodes_IsValidBidderCode(t *testing.T) {
 				Enabled: true,
 				Bidders: map[string]AdapterAlternateBidderCodes{
 					"pubmatic": {
+						Enabled:            true,
 						AllowedBidderCodes: []string{"*"},
 					},
 				},
@@ -811,6 +826,7 @@ func TestAlternateBidderCodes_IsValidBidderCode(t *testing.T) {
 				Enabled: true,
 				Bidders: map[string]AdapterAlternateBidderCodes{
 					"pubmatic": {
+						Enabled:            true,
 						AllowedBidderCodes: []string{"groupm"},
 					},
 				},
@@ -827,6 +843,7 @@ func TestAlternateBidderCodes_IsValidBidderCode(t *testing.T) {
 				Enabled: true,
 				Bidders: map[string]AdapterAlternateBidderCodes{
 					"pubmatic": {
+						Enabled:            true,
 						AllowedBidderCodes: []string{"xyz"},
 					},
 				},
@@ -834,6 +851,21 @@ func TestAlternateBidderCodes_IsValidBidderCode(t *testing.T) {
 			wantIsValid: false,
 			wantErr:     errors.New(`invalid biddercode "groupm" sent by adapter "pubmatic"`),
 		},
+		{
+			name: "account.alternatebiddercodes and adapter config enabled but adapter config has allowedBidderCodes list empty",
+			args: args{
+				bidder:          "pubmatic",
+				alternateBidder: "groupm",
+			},
+			fields: fields{
+				Enabled: true,
+				Bidders: map[string]AdapterAlternateBidderCodes{
+					"pubmatic": {Enabled: true, AllowedBidderCodes: []string{}},
+				},
+			},
+			wantIsValid: false,
+			wantErr:     errors.New(`invalid biddercode "groupm" sent by adapter "pubmatic"`),
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index 59929f21..54d326c4 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -878,22 +878,65 @@ func TestImplicitSecure(t *testing.T) {
 	}
 }
 
-func TestRefererParsing(t *testing.T) {
-	httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, "site.json")))
-	httpReq.Header.Set("Referer", "http://test.mysite.com")
-	bidReq := &openrtb2.BidRequest{}
+func TestReferer(t *testing.T) {
+	testCases := []struct {
+		description     string
+		givenSitePage   string
+		givenSiteDomain string
+		givenReferer    string
+		expectedDomain  string
+		expectedPage    string
+	}{
+		{
+			description:    "site.page/domain are unchanged when site.page/domain and http referer are not set",
+			expectedDomain: "",
+			expectedPage:   "",
+		},
+		{
+			description:    "site.page/domain are derived from referer when neither is set and http referer is set",
+			givenReferer:   "https://test.somepage.com",
+			expectedDomain: "somepage.com",
+			expectedPage:   "https://test.somepage.com",
+		},
+		{
+			description:    "site.domain is derived from site.page when site.page is set and http referer is not set",
+			givenSitePage:  "https://test.somepage.com",
+			expectedDomain: "somepage.com",
+			expectedPage:   "https://test.somepage.com",
+		},
+		{
+			description:    "site.domain is derived from http referer when site.page and http referer are set",
+			givenSitePage:  "https://test.somepage.com",
+			givenReferer:   "http://test.com",
+			expectedDomain: "test.com",
+			expectedPage:   "https://test.somepage.com",
+		},
+		{
+			description:     "site.page/domain are unchanged when site.page/domain and http referer are set",
+			givenSitePage:   "https://test.somepage.com",
+			givenSiteDomain: "some.domain.com",
+			givenReferer:    "http://test.com",
+			expectedDomain:  "some.domain.com",
+			expectedPage:    "https://test.somepage.com",
+		},
+	}
 
-	setSiteImplicitly(httpReq, bidReq)
+	for _, test := range testCases {
+		httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, "site.json")))
+		httpReq.Header.Set("Referer", test.givenReferer)
 
-	if bidReq.Site == nil {
-		t.Fatalf("bidrequest.site should not be nil.")
-	}
+		bidReq := &openrtb2.BidRequest{
+			Site: &openrtb2.Site{
+				Domain: test.givenSiteDomain,
+				Page:   test.givenSitePage,
+			},
+		}
 
-	if bidReq.Site.Domain != "mysite.com" {
-		t.Errorf("Bad bidrequest.site.domain. Expected mysite.com, got %s", bidReq.Site.Domain)
-	}
-	if bidReq.Site.Page != "http://test.mysite.com" {
-		t.Errorf("Bad bidrequest.site.page. Expected mysite.com, got %s", bidReq.Site.Page)
+		setSiteImplicitly(httpReq, bidReq)
+
+		assert.NotNil(t, bidReq.Site, test.description)
+		assert.Equal(t, test.expectedDomain, bidReq.Site.Domain, test.description)
+		assert.Equal(t, test.expectedPage, bidReq.Site.Page, test.description)
 	}
 }
 
@@ -917,6 +960,10 @@ func TestParseImpInfoSingleImpression(t *testing.T) {
 			Imp:          json.RawMessage(`{"id": "some-static-imp","video":{"mimes":["video/mp4"]},"ext": {"appnexus": {"placementId": "abc","position": "below"}}}`),
 			ImpExtPrebid: openrtb_ext.ExtImpPrebid{},
 		},
+		{
+			Imp:          json.RawMessage(`{"id":"my-imp-id", "video":{"h":300, "w":200}, "ext":{"prebid":{"storedrequest": {"id": "6"}}}}`),
+			ImpExtPrebid: openrtb_ext.ExtImpPrebid{StoredRequest: &openrtb_ext.ExtStoredRequest{ID: "6"}},
+		},
 	}
 
 	for i, requestData := range testStoredRequests {
@@ -1010,7 +1057,7 @@ func TestStoredRequests(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 	}
 
-	testStoreVideoAttr := []bool{true, true, false, false}
+	testStoreVideoAttr := []bool{true, true, false, false, false}
 
 	for i, requestData := range testStoredRequests {
 		impInfo, errs := parseImpInfo([]byte(requestData))
@@ -1026,7 +1073,6 @@ func TestStoredRequests(t *testing.T) {
 			}
 		}
 		expectJson := json.RawMessage(testFinalRequests[i])
-
 		assert.JSONEq(t, string(expectJson), string(newRequest), "Incorrect result request %d", i)
 
 		expectedImp := testStoredImpIds[i]
diff --git a/endpoints/openrtb2/test_utils.go b/endpoints/openrtb2/test_utils.go
index 82fd78fa..38497581 100644
--- a/endpoints/openrtb2/test_utils.go
+++ b/endpoints/openrtb2/test_utils.go
@@ -119,6 +119,17 @@ var testStoredRequestData = map[string]json.RawMessage{
 		}`),
 	// Valid JSON
 	"4": json.RawMessage(`{"id": "ThisID", "cur": ["USD"]}`),
+
+	// Stored Request with Root Ext Passthrough
+	"5": json.RawMessage(`{
+		"ext": {
+			"prebid": {
+				"passthrough": {
+					"root_ext_passthrough": 20
+				}
+			}
+		}
+	}`),
 }
 
 // Stored Imp Requests
@@ -197,6 +208,17 @@ var testStoredImpData = map[string]json.RawMessage{
 				}
 			}
 		}`),
+	// Stored Imp with Passthrough
+	"6": json.RawMessage(`{
+		"id": "my-imp-id",
+		"ext": {
+			"prebid": {
+				"passthrough": {
+					"imp_passthrough": 30
+				}
+			}
+		}
+	}`),
 }
 
 // Incoming requests with stored request IDs
@@ -323,6 +345,32 @@ var testStoredRequests = []string{
 			}
 		}
 	}`,
+	`{
+		"id": "ThisID",
+		"imp": [
+			{
+				"id": "my-imp-id",
+				"video":{
+					"h":300,
+					"w":200
+				},
+				"ext": {
+					"prebid": {
+						"storedrequest": {
+							"id": "6"
+						}
+					}
+				}
+			}
+		],
+		"ext": {
+			"prebid": {
+				"storedrequest": {
+					"id": "5"
+				}
+			}
+		}
+	}`,
 }
 
 // The expected requests after stored request processing
@@ -438,8 +486,7 @@ var testFinalRequests = []string{
   		  }
   		],
   		"tmax": 500
-	}
-`,
+	}`,
 	`{
 	"id": "ThisID",
 	"imp": [
@@ -489,11 +536,43 @@ var testFinalRequests = []string{
 			}
 		}
 	}
+}`,
+	`{
+	"id": "ThisID",
+	"imp": [
+		{
+			"ext":{
+			   "prebid":{
+				  "passthrough":{
+					 "imp_passthrough":30
+				  },
+				  "storedrequest":{
+					 "id":"6"
+				  }
+			   }
+			},
+			"id":"my-imp-id",
+			"video":{
+			   "h":300,
+			   "w":200
+			}
+		 }
+	],
+	"ext":{
+		"prebid":{
+		   "passthrough":{
+			  "root_ext_passthrough":20
+		   },
+		   "storedrequest":{
+			  "id":"5"
+		   }
+		}
+	 }
 }`,
 }
 
 var testStoredImpIds = []string{
-	"adUnit1", "adUnit2", "adUnit1", "some-static-imp",
+	"adUnit1", "adUnit2", "adUnit1", "some-static-imp", "my-imp-id",
 }
 
 var testStoredImps = []string{
@@ -545,6 +624,16 @@ var testStoredImps = []string{
 			}
 		}`,
 	``,
+	`{
+		"id": "my-imp-id",
+		"ext": {
+			"prebid": {
+				"passthrough": {
+					"imp_passthrough": 30
+				}
+			}
+		}
+	}`,
 }
 
 var testBidRequests = []string{
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index e9b32322..295eeaf1 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -11,6 +11,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/prebid/prebid-server/analytics"
 	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/gdpr"
 	"github.com/prebid/prebid-server/metrics"
@@ -255,10 +256,12 @@ func TestSetUIDEndpoint(t *testing.T) {
 		},
 	}
 
+	analytics := analyticsConf.NewPBSAnalytics(&config.Analytics{})
 	metrics := &metricsConf.NilMetricsEngine{}
+
 	for _, test := range testCases {
-		response := doRequest(makeRequest(test.uri, test.existingSyncs), metrics,
-			test.syncersBidderNameToKey, test.gdprAllowsHostCookies, test.gdprReturnsError, test.gdprMalformed)
+		response := doRequest(makeRequest(test.uri, test.existingSyncs), analytics, metrics,
+			test.syncersBidderNameToKey, test.gdprAllowsHostCookies, test.gdprReturnsError, test.gdprMalformed, false)
 		assert.Equal(t, test.expectedStatusCode, response.Code, "Test Case: %s. /setuid returned unexpected error code", test.description)
 
 		if test.expectedSyncs != nil {
@@ -295,8 +298,10 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 		cookies                []*usersync.Cookie
 		syncersBidderNameToKey map[string]string
 		gdprAllowsHostCookies  bool
+		cfgAccountRequired     bool
 		expectedResponseCode   int
 		expectedMetrics        func(*metrics.MetricsEngineMock)
+		expectedAnalytics      func(*MockAnalytics)
 	}{
 		{
 			description:            "Success - Sync",
@@ -309,6 +314,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 				m.On("RecordSetUid", metrics.SetUidOK).Once()
 				m.On("RecordSyncerSet", "pubmatic", metrics.SyncerSetUidOK).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  200,
+					Bidder:  "pubmatic",
+					UID:     "123",
+					Errors:  []error{},
+					Success: true,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 		{
 			description:            "Success - Unsync",
@@ -321,6 +336,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 				m.On("RecordSetUid", metrics.SetUidOK).Once()
 				m.On("RecordSyncerSet", "pubmatic", metrics.SyncerSetUidCleared).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  200,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{},
+					Success: true,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 		{
 			description:            "Cookie Opted Out",
@@ -332,6 +357,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 			expectedMetrics: func(m *metrics.MetricsEngineMock) {
 				m.On("RecordSetUid", metrics.SetUidOptOut).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  401,
+					Bidder:  "",
+					UID:     "",
+					Errors:  []error{},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 		{
 			description:            "Unknown Syncer Key",
@@ -343,6 +378,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 			expectedMetrics: func(m *metrics.MetricsEngineMock) {
 				m.On("RecordSetUid", metrics.SetUidSyncerUnknown).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  400,
+					Bidder:  "",
+					UID:     "",
+					Errors:  []error{errors.New("The bidder name provided is not supported by Prebid Server")},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 		{
 			description:            "Unknown Format",
@@ -354,6 +399,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 			expectedMetrics: func(m *metrics.MetricsEngineMock) {
 				m.On("RecordSetUid", metrics.SetUidBadRequest).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  400,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{errors.New(`"f" query param is invalid. must be "b" or "i"`)},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 		{
 			description:            "Prevented By GDPR - Invalid Consent String",
@@ -365,6 +420,16 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 			expectedMetrics: func(m *metrics.MetricsEngineMock) {
 				m.On("RecordSetUid", metrics.SetUidBadRequest).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  400,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{errors.New("gdpr_consent is required when gdpr=1")},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 		{
 			description:            "Prevented By GDPR - Permission Denied By Consent String",
@@ -376,10 +441,88 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 			expectedMetrics: func(m *metrics.MetricsEngineMock) {
 				m.On("RecordSetUid", metrics.SetUidGDPRHostCookieBlocked).Once()
 			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  451,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{errors.New("The gdpr_consent string prevents cookies from being saved")},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
+		},
+		{
+			description:            "Blocked account",
+			uri:                    "/setuid?bidder=pubmatic&uid=123&account=blocked_acct",
+			cookies:                []*usersync.Cookie{},
+			syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
+			gdprAllowsHostCookies:  true,
+			expectedResponseCode:   400,
+			expectedMetrics: func(m *metrics.MetricsEngineMock) {
+				m.On("RecordSetUid", metrics.SetUidAccountBlocked).Once()
+			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  400,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{errCookieSyncAccountBlocked},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
+		},
+		{
+			description:            "Invalid account",
+			uri:                    "/setuid?bidder=pubmatic&uid=123&account=unknown",
+			cookies:                []*usersync.Cookie{},
+			syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
+			gdprAllowsHostCookies:  true,
+			cfgAccountRequired:     true,
+			expectedResponseCode:   400,
+			expectedMetrics: func(m *metrics.MetricsEngineMock) {
+				m.On("RecordSetUid", metrics.SetUidAccountInvalid).Once()
+			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  400,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{errCookieSyncAccountInvalid},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
+		},
+		{
+			description:            "Malformed account",
+			uri:                    "/setuid?bidder=pubmatic&uid=123&account=malformed_acct",
+			cookies:                []*usersync.Cookie{},
+			syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
+			gdprAllowsHostCookies:  true,
+			cfgAccountRequired:     true,
+			expectedResponseCode:   400,
+			expectedMetrics: func(m *metrics.MetricsEngineMock) {
+				m.On("RecordSetUid", metrics.SetUidBadRequest).Once()
+			},
+			expectedAnalytics: func(a *MockAnalytics) {
+				expected := analytics.SetUIDObject{
+					Status:  400,
+					Bidder:  "pubmatic",
+					UID:     "",
+					Errors:  []error{errors.New("json: cannot unmarshal string into Go struct field Account.disabled of type bool")},
+					Success: false,
+				}
+				a.On("LogSetUIDObject", &expected).Once()
+			},
 		},
 	}
 
 	for _, test := range testCases {
+		analyticsEngine := &MockAnalytics{}
+		test.expectedAnalytics(analyticsEngine)
+
 		metricsEngine := &metrics.MetricsEngineMock{}
 		test.expectedMetrics(metricsEngine)
 
@@ -387,9 +530,10 @@ func TestSetUIDEndpointMetrics(t *testing.T) {
 		for _, v := range test.cookies {
 			addCookie(req, v)
 		}
-		response := doRequest(req, metricsEngine, test.syncersBidderNameToKey, test.gdprAllowsHostCookies, false, false)
+		response := doRequest(req, analyticsEngine, metricsEngine, test.syncersBidderNameToKey, test.gdprAllowsHostCookies, false, false, test.cfgAccountRequired)
 
 		assert.Equal(t, test.expectedResponseCode, response.Code, test.description)
+		analyticsEngine.AssertExpectations(t)
 		metricsEngine.AssertExpectations(t)
 	}
 }
@@ -400,8 +544,9 @@ func TestOptedOut(t *testing.T) {
 	cookie.SetOptOut(true)
 	addCookie(request, cookie)
 	syncersBidderNameToKey := map[string]string{"pubmatic": "pubmatic"}
+	analytics := analyticsConf.NewPBSAnalytics(&config.Analytics{})
 	metrics := &metricsConf.NilMetricsEngine{}
-	response := doRequest(request, metrics, syncersBidderNameToKey, true, false, false)
+	response := doRequest(request, analytics, metrics, syncersBidderNameToKey, true, false, false, false)
 
 	assert.Equal(t, http.StatusUnauthorized, response.Code)
 }
@@ -537,8 +682,13 @@ func makeRequest(uri string, existingSyncs map[string]string) *http.Request {
 	return request
 }
 
-func doRequest(req *http.Request, metrics metrics.MetricsEngine, syncersBidderNameToKey map[string]string, gdprAllowsHostCookies, gdprReturnsError, gdprReturnsMalformedError bool) *httptest.ResponseRecorder {
-	cfg := config.Configuration{}
+func doRequest(req *http.Request, analytics analytics.PBSAnalyticsModule, metrics metrics.MetricsEngine, syncersBidderNameToKey map[string]string, gdprAllowsHostCookies, gdprReturnsError, gdprReturnsMalformedError, cfgAccountRequired bool) *httptest.ResponseRecorder {
+	cfg := config.Configuration{
+		AccountRequired: cfgAccountRequired,
+		BlacklistedAcctMap: map[string]bool{
+			"blocked_acct": true,
+		},
+	}
 	cfg.MarshalAccountDefaults()
 
 	query := req.URL.Query()
@@ -557,15 +707,15 @@ func doRequest(req *http.Request, metrics metrics.MetricsEngine, syncersBidderNa
 		cfg: gdpr.NewTCF2Config(config.TCF2{}, config.AccountGDPR{}),
 	}.Builder
 
-	analytics := analyticsConf.NewPBSAnalytics(&cfg.Analytics)
 	syncersByBidder := make(map[string]usersync.Syncer)
 	for bidderName, syncerKey := range syncersBidderNameToKey {
 		syncersByBidder[bidderName] = fakeSyncer{key: syncerKey, defaultSyncType: usersync.SyncTypeIFrame}
 	}
 
 	fakeAccountsFetcher := FakeAccountsFetcher{AccountData: map[string]json.RawMessage{
-		"valid_acct":    json.RawMessage(`{"disabled":false}`),
-		"disabled_acct": json.RawMessage(`{"disabled":true}`),
+		"valid_acct":     json.RawMessage(`{"disabled":false}`),
+		"disabled_acct":  json.RawMessage(`{"disabled":true}`),
+		"malformed_acct": json.RawMessage(`{"disabled":"malformed"}`),
 	}}
 
 	endpoint := NewSetUIDEndpoint(&cfg, syncersByBidder, gdprPermsBuilder, tcf2ConfigBuilder, analytics, fakeAccountsFetcher, metrics)
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index 6bea9ce2..2d5d4e69 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -2243,6 +2243,7 @@ func TestExtraBid(t *testing.T) {
 			Enabled: true,
 			Bidders: map[string]config.AdapterAlternateBidderCodes{
 				string(openrtb_ext.BidderPubmatic): {
+					Enabled:            true,
 					AllowedBidderCodes: []string{"groupm"},
 				},
 			},
@@ -2354,6 +2355,7 @@ func TestExtraBidWithAlternateBidderCodeDisabled(t *testing.T) {
 			Enabled: true,
 			Bidders: map[string]config.AdapterAlternateBidderCodes{
 				string(openrtb_ext.BidderPubmatic): {
+					Enabled:            true,
 					AllowedBidderCodes: []string{"groupm-allowed"},
 				},
 			},
@@ -2462,6 +2464,7 @@ func TestExtraBidWithBidAdjustments(t *testing.T) {
 			Enabled: true,
 			Bidders: map[string]config.AdapterAlternateBidderCodes{
 				string(openrtb_ext.BidderPubmatic): {
+					Enabled:            true,
 					AllowedBidderCodes: []string{"groupm"},
 				},
 			},
@@ -2572,6 +2575,7 @@ func TestExtraBidWithBidAdjustmentsUsingAdapterCode(t *testing.T) {
 			Enabled: true,
 			Bidders: map[string]config.AdapterAlternateBidderCodes{
 				string(openrtb_ext.BidderPubmatic): {
+					Enabled:            true,
 					AllowedBidderCodes: []string{"groupm"},
 				},
 			},
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 9c22add4..6c649d30 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -1818,9 +1818,10 @@ func TestBidResponseImpExtInfo(t *testing.T) {
 	impExtInfo := make(map[string]ImpExtInfo, 1)
 	impExtInfo["some-impression-id"] = ImpExtInfo{
 		true,
-		[]byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}
+		[]byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`),
+		json.RawMessage(`{"imp_passthrough_val": 1}`)}
 
-	expectedBidResponseExt := `{"origbidcpm":0,"prebid":{"type":"video"},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]}}`
+	expectedBidResponseExt := `{"origbidcpm":0,"prebid":{"type":"video","passthrough":{"imp_passthrough_val":1}},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]}}`
 
 	actualBidResp, err := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, nil, nil, nil, true, impExtInfo, errList)
 	assert.NoError(t, err, fmt.Sprintf("imp ext info was not passed through correctly: %s", err))
@@ -2216,6 +2217,16 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 		debugLog.Regexp = regexp.MustCompile(`[<>]`)
 	}
 
+	// Passthrough JSON Testing
+	impExtInfoMap := make(map[string]ImpExtInfo)
+	if spec.PassthroughFlag {
+		impPassthrough, impID, err := getInfoFromImp(&openrtb_ext.RequestWrapper{BidRequest: &spec.IncomingRequest.OrtbRequest})
+		if err != nil {
+			t.Errorf("%s: Exchange returned an unexpected error. Got %s", filename, err.Error())
+		}
+		impExtInfoMap[impID] = ImpExtInfo{Passthrough: impPassthrough}
+	}
+
 	auctionRequest := AuctionRequest{
 		BidRequestWrapper: &openrtb_ext.RequestWrapper{BidRequest: &spec.IncomingRequest.OrtbRequest},
 		Account: config.Account{
@@ -2223,8 +2234,10 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 			EventsEnabled: spec.EventsEnabled,
 			DebugAllow:    true,
 		},
-		UserSyncs: mockIdFetcher(spec.IncomingRequest.Usersyncs),
+		UserSyncs:     mockIdFetcher(spec.IncomingRequest.Usersyncs),
+		ImpExtInfoMap: impExtInfoMap,
 	}
+
 	if spec.StartTime > 0 {
 		auctionRequest.StartTime = time.Unix(0, spec.StartTime*1e+6)
 	}
@@ -2273,6 +2286,22 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 		//compare debug info
 		assert.JSONEq(t, string(bid.Ext), string(spec.Response.Ext), "Debug info modified")
 	}
+
+	if spec.PassthroughFlag {
+		var actualBidRespExt openrtb_ext.ExtBidResponse
+		var expectedBidRespExt openrtb_ext.ExtBidResponse
+		if bid.Ext != nil {
+			if err := json.Unmarshal(bid.Ext, &actualBidRespExt); err != nil {
+				assert.NoError(t, err, fmt.Sprintf("Error when unmarshalling: %s", err))
+			}
+		}
+		if spec.Response.Ext != nil {
+			if err := json.Unmarshal(spec.Response.Ext, &expectedBidRespExt); err != nil {
+				assert.NoError(t, err, fmt.Sprintf("Error when unmarshalling: %s", err))
+			}
+		}
+		assert.Equalf(t, expectedBidRespExt.Prebid, actualBidRespExt.Prebid, "Expected bid response extension is incorrect")
+	}
 }
 
 func findBiddersInAuction(t *testing.T, context string, req *openrtb2.BidRequest) []string {
@@ -3607,18 +3636,18 @@ func TestMakeBidExtJSON(t *testing.T) {
 		{
 			description:        "Valid extension, non empty extBidPrebid, valid imp ext info, meta from adapter",
 			ext:                json.RawMessage(`{"video":{"h":100}}`),
-			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video"), Meta: &openrtb_ext.ExtBidPrebidMeta{BrandName: "foo"}},
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
+			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video"), Meta: &openrtb_ext.ExtBidPrebidMeta{BrandName: "foo"}, Passthrough: nil},
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
-			expectedBidExt:     `{"prebid":{"meta": {"brandName": "foo"}, "type":"video"},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
+			expectedBidExt:     `{"prebid":{"meta": {"brandName": "foo"}, "passthrough":{"imp_passthrough_val":1}, "type":"video"}, "storedrequestattributes":{"h":480,"mimes":["video/mp4"]},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
 			expectedErrMessage: "",
 		},
 		{
-			description:        "Valid extension, non empty extBidPrebid, valid imp ext info, meta from response",
+			description:        "Valid extension, non empty extBidPrebid, valid imp ext info, meta from response, imp passthrough is nil",
 			ext:                json.RawMessage(`{"video":{"h":100},"prebid":{"meta": {"brandName": "foo"}}}`),
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), nil}},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
 			expectedBidExt:     `{"prebid":{"meta": {"brandName": "foo"}, "type":"video"},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
@@ -3628,16 +3657,16 @@ func TestMakeBidExtJSON(t *testing.T) {
 			description:        "Empty extension, non empty extBidPrebid and valid imp ext info",
 			ext:                nil,
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
 			origbidcpm:         0,
-			expectedBidExt:     `{"origbidcpm": 0,"prebid":{"type":"video"},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]}}`,
+			expectedBidExt:     `{"origbidcpm": 0,"prebid":{"passthrough":{"imp_passthrough_val":1}, "type":"video"},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]}}`,
 			expectedErrMessage: "",
 		},
 		{
 			description:        "Valid extension, non empty extBidPrebid and imp ext info not found",
 			ext:                json.RawMessage(`{"video":{"h":100}}`),
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
-			impExtInfo:         map[string]ImpExtInfo{"another_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
+			impExtInfo:         map[string]ImpExtInfo{"another_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
 			expectedBidExt:     `{"prebid":{"type":"video"},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
@@ -3649,8 +3678,8 @@ func TestMakeBidExtJSON(t *testing.T) {
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
-			expectedBidExt:     `{"prebid":{"type":""},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
+			expectedBidExt:     `{"prebid":{"passthrough":{"imp_passthrough_val":1}, "type":""},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
 			expectedErrMessage: "",
 		},
 		{
@@ -3669,8 +3698,8 @@ func TestMakeBidExtJSON(t *testing.T) {
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"banner":{"h":480}}`)}},
-			expectedBidExt:     `{"prebid":{"type":"video"},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"banner":{"h":480}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
+			expectedBidExt:     `{"prebid":{"passthrough":{"imp_passthrough_val":1}, "type":"video"},"video":{"h":100}, "origbidcpm": 10, "origbidcur": "USD"}`,
 			expectedErrMessage: "",
 		},
 		{
@@ -3679,8 +3708,8 @@ func TestMakeBidExtJSON(t *testing.T) {
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"banner":{"h":480}}`)}},
-			expectedBidExt:     `{"prebid":{"type":"video"}, "origbidcpm": 10, "origbidcur": "USD"}`,
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"banner":{"h":480}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
+			expectedBidExt:     `{"prebid":{"passthrough":{"imp_passthrough_val":1}, "type":"video"}, "origbidcpm": 10, "origbidcur": "USD"}`,
 			expectedErrMessage: "",
 		},
 		{
@@ -3689,8 +3718,8 @@ func TestMakeBidExtJSON(t *testing.T) {
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
 			origbidcpm:         10.0000,
 			origbidcur:         "USD",
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
-			expectedBidExt:     `{"prebid":{"type":"video"}, "storedrequestattributes":{"h":480,"mimes":["video/mp4"]}, "origbidcpm": 10, "origbidcur": "USD"}`,
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), json.RawMessage(`{"imp_passthrough_val": 1}`)}},
+			expectedBidExt:     `{"prebid":{"passthrough":{"imp_passthrough_val":1}, "type":"video"}, "storedrequestattributes":{"h":480,"mimes":["video/mp4"]}, "origbidcpm": 10, "origbidcur": "USD"}`,
 			expectedErrMessage: "",
 		},
 		{
@@ -3758,7 +3787,7 @@ func TestMakeBidExtJSON(t *testing.T) {
 			description:        "Invalid extension, valid extBidPrebid and valid imp ext info",
 			ext:                json.RawMessage(`{invalid json}`),
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{Type: openrtb_ext.BidType("video")},
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`)}},
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{"h":480,"mimes":["video/mp4"]}}`), json.RawMessage(`"prebid": {"passthrough": {"imp_passthrough_val": some_val}}"`)}},
 			expectedBidExt:     ``,
 			expectedErrMessage: "invalid character",
 		},
@@ -3766,7 +3795,7 @@ func TestMakeBidExtJSON(t *testing.T) {
 			description:        "Valid extension, empty extBidPrebid and invalid imp ext info",
 			ext:                json.RawMessage(`{"video":{"h":100}}`),
 			extBidPrebid:       openrtb_ext.ExtBidPrebid{},
-			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{!}}`)}},
+			impExtInfo:         map[string]ImpExtInfo{"test_imp_id": {true, []byte(`{"video":{!}}`), nil}},
 			expectedBidExt:     ``,
 			expectedErrMessage: "invalid character",
 		},
@@ -4211,6 +4240,7 @@ type exchangeSpec struct {
 	StartTime         int64                  `json:"start_time_ms,omitempty"`
 	BidIDGenerator    *mockBidIDGenerator    `json:"bidIDGenerator,omitempty"`
 	RequestType       *metrics.RequestType   `json:"requestType,omitempty"`
+	PassthroughFlag   bool                   `json:"passthrough_flag,omitempty"`
 	HostSChainFlag    bool                   `json:"host_schain_flag,omitempty"`
 }
 
@@ -4375,7 +4405,6 @@ func diffOrtbResponses(t *testing.T, description string, expected *openrtb2.BidR
 	if err != nil {
 		t.Fatalf("%s failed to marshal expected BidResponse into JSON. %v", description, err)
 	}
-
 	assert.JSONEq(t, string(expectedJSON), string(actualJSON), description)
 }
 
@@ -4494,3 +4523,22 @@ func (m *mockBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequ
 	args := m.Called(internalRequest, externalRequest, response)
 	return args.Get(0).(*adapters.BidderResponse), args.Get(1).([]error)
 }
+
+func getInfoFromImp(req *openrtb_ext.RequestWrapper) (json.RawMessage, string, error) {
+	bidRequest := req.BidRequest
+	imp := bidRequest.Imp[0]
+	impID := imp.ID
+
+	var bidderExts map[string]json.RawMessage
+	if err := json.Unmarshal(imp.Ext, &bidderExts); err != nil {
+		return nil, "", err
+	}
+
+	var extPrebid openrtb_ext.ExtImpPrebid
+	if bidderExts[openrtb_ext.PrebidExtKey] != nil {
+		if err := json.Unmarshal(bidderExts[openrtb_ext.PrebidExtKey], &extPrebid); err != nil {
+			return nil, "", err
+		}
+	}
+	return extPrebid.Passthrough, impID, nil
+}
diff --git a/exchange/exchangetest/aliases.json b/exchange/exchangetest/aliases.json
index 59f270e1..8c0bf309 100644
--- a/exchange/exchangetest/aliases.json
+++ b/exchange/exchangetest/aliases.json
@@ -58,11 +58,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              }
-            }
+            "prebid": {}
           }
         }
       },
@@ -94,11 +90,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              }
-            }
+            "prebid": {}
           }
         }
       },
diff --git a/exchange/exchangetest/bidadjustmentfactors.json b/exchange/exchangetest/bidadjustmentfactors.json
index 1f096bfb..8ef413ee 100644
--- a/exchange/exchangetest/bidadjustmentfactors.json
+++ b/exchange/exchangetest/bidadjustmentfactors.json
@@ -56,15 +56,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              },
-              "bidadjustmentfactors": {
-                "appnexus": 2.5,
-                "districtm": 0.3
-              }
-            }
+            "prebid": {}
           }
         },
         "bidAdjustments": {
@@ -97,15 +89,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              },
-              "bidadjustmentfactors": {
-                "appnexus": 2.5,
-                "districtm": 0.3
-              }
-            }
+            "prebid": {}
           }
         },
         "bidAdjustments": {
@@ -129,4 +113,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/ccpa-nosale-any-bidder.json b/exchange/exchangetest/ccpa-nosale-any-bidder.json
index db98878d..1774ba7a 100644
--- a/exchange/exchangetest/ccpa-nosale-any-bidder.json
+++ b/exchange/exchangetest/ccpa-nosale-any-bidder.json
@@ -6,17 +6,19 @@
             "site": {
                 "page": "test.somepage.com"
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "appnexus": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }],
+            ],
             "regs": {
                 "ext": {
                     "us_privacy": "1-Y-"
@@ -40,26 +42,26 @@
                     "site": {
                         "page": "test.somepage.com"
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }],
+                    ],
                     "regs": {
                         "ext": {
                             "us_privacy": "1-Y-"
                         }
                     },
                     "ext": {
-                        "prebid": {
-                            "nosale": ["*"]
-                        }
+                        "prebid": {}
                     },
                     "user": {
                         "buyeruid": "some-buyer-id"
diff --git a/exchange/exchangetest/ccpa-nosale-specific-bidder.json b/exchange/exchangetest/ccpa-nosale-specific-bidder.json
index ffa4e9c7..219aac48 100644
--- a/exchange/exchangetest/ccpa-nosale-specific-bidder.json
+++ b/exchange/exchangetest/ccpa-nosale-specific-bidder.json
@@ -6,17 +6,19 @@
             "site": {
                 "page": "test.somepage.com"
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "appnexus": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }],
+            ],
             "regs": {
                 "ext": {
                     "us_privacy": "1-Y-"
@@ -40,26 +42,26 @@
                     "site": {
                         "page": "test.somepage.com"
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }],
+                    ],
                     "regs": {
                         "ext": {
                             "us_privacy": "1-Y-"
                         }
                     },
                     "ext": {
-                        "prebid": {
-                            "nosale": ["appnexus"]
-                        }
+                        "prebid": {}
                     },
                     "user": {
                         "buyeruid": "some-buyer-id"
diff --git a/exchange/exchangetest/eidpermissions-allowed-alias.json b/exchange/exchangetest/eidpermissions-allowed-alias.json
index 305c1823..fc12c271 100644
--- a/exchange/exchangetest/eidpermissions-allowed-alias.json
+++ b/exchange/exchangetest/eidpermissions-allowed-alias.json
@@ -7,10 +7,12 @@
             },
             "user": {
                 "ext": {
-                    "eids": [{
-                        "source": "source1",
-                        "id": "anyId"
-                    }]
+                    "eids": [
+                        {
+                            "source": "source1",
+                            "id": "anyId"
+                        }
+                    ]
                 }
             },
             "ext": {
@@ -19,24 +21,28 @@
                         "foo": "appnexus"
                     },
                     "data": {
-                        "eidpermissions": [{
-                            "source": "source1",
-                            "bidders": ["foo"]
-                        }]
+                        "eidpermissions": [
+                            {
+                                "source": "source1",
+                                "bidders": ["foo"]
+                            }
+                        ]
                     }
                 }
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "foo": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "foo": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }]
+            ]
         }
     },
     "outgoingRequests": {
@@ -49,76 +55,78 @@
                     },
                     "user": {
                         "ext": {
-                            "eids": [{
-                                "source": "source1",
-                                "id": "anyId"
-                            }]
+                            "eids": [
+                                {
+                                    "source": "source1",
+                                    "id": "anyId"
+                                }
+                            ]
                         }
                     },
                     "ext": {
-                        "prebid": {
-                            "aliases": {
-                                "foo": "appnexus"
-                            },
-                            "data": {
-                                "eidpermissions": [{
-                                    "source": "source1",
-                                    "bidders": ["foo"]
-                                }]
-                            }
-                        }
+                        "prebid": {}
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }]
+                    ]
                 }
             },
             "mockResponse": {
-                "pbsSeatBids": [{
-                    "pbsBids": [{
-                        "ortbBid": {
-                            "id": "apn-bid",
-                            "impid": "my-imp-id",
-                            "price": 0.3,
-                            "w": 200,
-                            "h": 250,
-                            "crid": "creative-1"
-                        },
-                        "bidType": "video"
-                    }],
-                    "seat": "foo"
-                }]
+                "pbsSeatBids": [
+                    {
+                        "pbsBids": [
+                            {
+                                "ortbBid": {
+                                    "id": "apn-bid",
+                                    "impid": "my-imp-id",
+                                    "price": 0.3,
+                                    "w": 200,
+                                    "h": 250,
+                                    "crid": "creative-1"
+                                },
+                                "bidType": "video"
+                            }
+                        ],
+                        "seat": "foo"
+                    }
+                ]
             }
         }
     },
     "response": {
         "bids": {
             "id": "some-request-id",
-            "seatbid": [{
-                "seat": "foo",
-                "bid": [{
-                    "id": "apn-bid",
-                    "impid": "my-imp-id",
-                    "price": 0.3,
-                    "w": 200,
-                    "h": 250,
-                    "crid": "creative-1",
-                    "ext": {
-                        "origbidcpm": 0.3,
-                        "prebid": {
-                            "type": "video"
+            "seatbid": [
+                {
+                    "seat": "foo",
+                    "bid": [
+                        {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "origbidcpm": 0.3,
+                                "prebid": {
+                                    "type": "video"
+                                }
+                            }
                         }
-                    }
-                }]
-            }]
+                    ]
+                }
+            ]
         }
     }
 }
\ No newline at end of file
diff --git a/exchange/exchangetest/eidpermissions-allowed.json b/exchange/exchangetest/eidpermissions-allowed.json
index 4687ec5c..953f38f9 100644
--- a/exchange/exchangetest/eidpermissions-allowed.json
+++ b/exchange/exchangetest/eidpermissions-allowed.json
@@ -7,33 +7,39 @@
             },
             "user": {
                 "ext": {
-                    "eids": [{
-                        "source": "source1",
-                        "id": "anyId"
-                    }]
+                    "eids": [
+                        {
+                            "source": "source1",
+                            "id": "anyId"
+                        }
+                    ]
                 }
             },
             "ext": {
                 "prebid": {
                     "data": {
-                        "eidpermissions": [{
-                            "source": "source1",
-                            "bidders": ["appnexus"]
-                        }]
+                        "eidpermissions": [
+                            {
+                                "source": "source1",
+                                "bidders": ["appnexus"]
+                            }
+                        ]
                     }
                 }
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "appnexus": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }]
+            ]
         }
     },
     "outgoingRequests": {
@@ -46,73 +52,78 @@
                     },
                     "user": {
                         "ext": {
-                            "eids": [{
-                                "source": "source1",
-                                "id": "anyId"
-                            }]
+                            "eids": [
+                                {
+                                    "source": "source1",
+                                    "id": "anyId"
+                                }
+                            ]
                         }
                     },
                     "ext": {
-                        "prebid": {
-                            "data": {
-                                "eidpermissions": [{
-                                    "source": "source1",
-                                    "bidders": ["appnexus"]
-                                }]
-                            }
-                        }
+                        "prebid": {}
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }]
+                    ]
                 }
             },
             "mockResponse": {
-                "pbsSeatBids": [{
-                    "pbsBids": [{
-                        "ortbBid": {
-                            "id": "apn-bid",
-                            "impid": "my-imp-id",
-                            "price": 0.3,
-                            "w": 200,
-                            "h": 250,
-                            "crid": "creative-1"
-                        },
-                        "bidType": "video"
-                    }],
-                    "seat": "appnexus"
-                }]
+                "pbsSeatBids": [
+                    {
+                        "pbsBids": [
+                            {
+                                "ortbBid": {
+                                    "id": "apn-bid",
+                                    "impid": "my-imp-id",
+                                    "price": 0.3,
+                                    "w": 200,
+                                    "h": 250,
+                                    "crid": "creative-1"
+                                },
+                                "bidType": "video"
+                            }
+                        ],
+                        "seat": "appnexus"
+                    }
+                ]
             }
         }
     },
     "response": {
         "bids": {
             "id": "some-request-id",
-            "seatbid": [{
-                "seat": "appnexus",
-                "bid": [{
-                    "id": "apn-bid",
-                    "impid": "my-imp-id",
-                    "price": 0.3,
-                    "w": 200,
-                    "h": 250,
-                    "crid": "creative-1",
-                    "ext": {
-                        "origbidcpm": 0.3,
-                        "prebid": {
-                            "type": "video"
+            "seatbid": [
+                {
+                    "seat": "appnexus",
+                    "bid": [
+                        {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "origbidcpm": 0.3,
+                                "prebid": {
+                                    "type": "video"
+                                }
+                            }
                         }
-                    }
-                }]
-            }]
+                    ]
+                }
+            ]
         }
     }
 }
\ No newline at end of file
diff --git a/exchange/exchangetest/eidpermissions-denied.json b/exchange/exchangetest/eidpermissions-denied.json
index 373616f9..1fb91294 100644
--- a/exchange/exchangetest/eidpermissions-denied.json
+++ b/exchange/exchangetest/eidpermissions-denied.json
@@ -7,33 +7,39 @@
             },
             "user": {
                 "ext": {
-                    "eids": [{
-                        "source": "source1",
-                        "id": "anyId"
-                    }]
+                    "eids": [
+                        {
+                            "source": "source1",
+                            "id": "anyId"
+                        }
+                    ]
                 }
             },
             "ext": {
                 "prebid": {
                     "data": {
-                        "eidpermissions": [{
-                            "source": "source1",
-                            "bidders": ["otherBidder"]
-                        }]
+                        "eidpermissions": [
+                            {
+                                "source": "source1",
+                                "bidders": ["otherBidder"]
+                            }
+                        ]
                     }
                 }
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "appnexus": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }]
+            ]
         }
     },
     "outgoingRequests": {
@@ -44,69 +50,71 @@
                     "site": {
                         "page": "test.somepage.com"
                     },
-                    "user": {
-                    },
+                    "user": {},
                     "ext": {
-                        "prebid": {
-                            "data": {
-                                "eidpermissions": [{
-                                    "source": "source1",
-                                    "bidders": ["otherBidder"]
-                                }]
-                            }
-                        }
+                        "prebid": {}
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }]
+                    ]
                 }
             },
             "mockResponse": {
-                "pbsSeatBids": [{
-                    "pbsBids": [{
-                        "ortbBid": {
-                            "id": "apn-bid",
-                            "impid": "my-imp-id",
-                            "price": 0.3,
-                            "w": 200,
-                            "h": 250,
-                            "crid": "creative-1"
-                        },
-                        "bidType": "video"
-                    }],
-                    "seat": "appnexus"
-                }]
+                "pbsSeatBids": [
+                    {
+                        "pbsBids": [
+                            {
+                                "ortbBid": {
+                                    "id": "apn-bid",
+                                    "impid": "my-imp-id",
+                                    "price": 0.3,
+                                    "w": 200,
+                                    "h": 250,
+                                    "crid": "creative-1"
+                                },
+                                "bidType": "video"
+                            }
+                        ],
+                        "seat": "appnexus"
+                    }
+                ]
             }
         }
     },
     "response": {
         "bids": {
             "id": "some-request-id",
-            "seatbid": [{
-                "seat": "appnexus",
-                "bid": [{
-                    "id": "apn-bid",
-                    "impid": "my-imp-id",
-                    "price": 0.3,
-                    "w": 200,
-                    "h": 250,
-                    "crid": "creative-1",
-                    "ext": {
-                        "origbidcpm": 0.3,
-                        "prebid": {
-                            "type": "video"
+            "seatbid": [
+                {
+                    "seat": "appnexus",
+                    "bid": [
+                        {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "origbidcpm": 0.3,
+                                "prebid": {
+                                    "type": "video"
+                                }
+                            }
                         }
-                    }
-                }]
-            }]
+                    ]
+                }
+            ]
         }
     }
 }
\ No newline at end of file
diff --git a/exchange/exchangetest/firstpartydata-multibidder-config-valid.json b/exchange/exchangetest/firstpartydata-multibidder-config-valid.json
index 8ac7e7d2..8788d553 100644
--- a/exchange/exchangetest/firstpartydata-multibidder-config-valid.json
+++ b/exchange/exchangetest/firstpartydata-multibidder-config-valid.json
@@ -105,11 +105,7 @@
             "page": "fpd_appnexus_site_page"
           },
           "ext": {
-            "prebid": {
-              "data": {
-                "eidpermissions": null
-              }
-            }
+            "prebid": {}
           }
         }
       }
@@ -147,15 +143,10 @@
             "page": "fpd_rubicon_site_page"
           },
           "ext": {
-            "prebid": {
-              "data": {
-                "eidpermissions": null
-              }
-            }
+            "prebid": {}
           }
         }
       }
     }
   }
-
 }
\ No newline at end of file
diff --git a/exchange/exchangetest/passthrough_imp_only.json b/exchange/exchangetest/passthrough_imp_only.json
new file mode 100644
index 00000000..e389a213
--- /dev/null
+++ b/exchange/exchangetest/passthrough_imp_only.json
@@ -0,0 +1,148 @@
+{
+    "passthrough_flag": true,
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id-2",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    },
+                    "prebid": {
+                        "passthrough": {
+                            "imp_passthrough_val": 20
+                        }
+                    }
+                }
+            },
+            {
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }]
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id-2",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    },
+                    {
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }]
+                }
+            },
+            "mockResponse": {
+                "pbsSeatBids": [{
+                    "pbsBids": [{
+                        "ortbBid": {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id-2",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "someField": "someValue",
+                                "origbidcpm": 0.3
+                            }
+                        },
+                        "bidType": "video"
+                    },
+                    {
+                        "ortbBid": {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "someField": "someValue",
+                                "origbidcpm": 0.3
+                            }
+                        },
+                        "bidType": "video"
+                    }],
+                    "seat": "appnexus"
+                }]
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "some-request-id",
+            "seatbid": [{
+                "seat": "appnexus",
+                "bid": [{
+                    "id": "apn-bid",
+                    "impid": "my-imp-id-2",
+                    "price": 0.3,
+                    "w": 200,
+                    "h": 250,
+                    "crid": "creative-1",
+                    "ext": {
+                        "someField": "someValue",
+                        "origbidcpm": 0.3,
+                        "prebid": {
+                            "type": "video",
+                            "passthrough": {
+                                "imp_passthrough_val": 20
+                            }
+                        }
+                    }
+                },
+                {
+                    "id": "apn-bid",
+                    "impid": "my-imp-id",
+                    "price": 0.3,
+                    "w": 200,
+                    "h": 250,
+                    "crid": "creative-1",
+                    "ext": {
+                        "someField": "someValue",
+                        "origbidcpm": 0.3,
+                        "prebid": {
+                            "type": "video"
+                        }
+                    }
+                }]
+            }]
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/passthrough_root_and_imp.json b/exchange/exchangetest/passthrough_root_and_imp.json
new file mode 100644
index 00000000..423bad37
--- /dev/null
+++ b/exchange/exchangetest/passthrough_root_and_imp.json
@@ -0,0 +1,109 @@
+{
+    "passthrough_flag": true,
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    },
+                    "prebid": {
+                        "passthrough": {
+                            "imp_passthrough_val": 20
+                        }
+                    }
+                }
+            }],
+            "ext": {
+                "prebid": {
+                    "passthrough": {"bid_response_passthrough":20}
+                }
+            }
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }],
+                    "ext": {
+                        "prebid": {}
+                    }
+                }
+            },
+            "mockResponse": {
+                "pbsSeatBids": [{
+                    "pbsBids": [{
+                        "ortbBid": {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "someField": "someValue",
+                                "origbidcpm": 0.3
+                            }
+                        },
+                        "bidType": "video"
+                    }],
+                    "seat": "appnexus"
+                }]
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "some-request-id",
+            "seatbid": [{
+                "seat": "appnexus",
+                "bid": [{
+                    "id": "apn-bid",
+                    "impid": "my-imp-id",
+                    "price": 0.3,
+                    "w": 200,
+                    "h": 250,
+                    "crid": "creative-1",
+                    "ext": {
+                        "someField": "someValue",
+                        "origbidcpm": 0.3,
+                        "prebid": {
+                            "type": "video",
+                            "passthrough": {
+                                "imp_passthrough_val": 20
+                            }
+                        }
+                    }
+                }]
+            }]
+        },
+        "ext": {
+            "prebid": {
+                "passthrough": {"bid_response_passthrough":20}
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/passthrough_root_only.json b/exchange/exchangetest/passthrough_root_only.json
new file mode 100644
index 00000000..c84f1927
--- /dev/null
+++ b/exchange/exchangetest/passthrough_root_only.json
@@ -0,0 +1,101 @@
+{
+    "passthrough_flag": true,
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }],
+            "ext": {
+                "prebid": {
+                    "passthrough": {"bid_response_passthrough":20}
+                }
+            }
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }],
+                    "ext": {
+                        "prebid": {}
+                    }
+                }
+            },
+            "mockResponse": {
+                "pbsSeatBids": [{
+                    "pbsBids": [{
+                        "ortbBid": {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "someField": "someValue",
+                                "origbidcpm": 0.3
+                            }
+                        },
+                        "bidType": "video"
+                    }],
+                    "seat": "appnexus"
+                }]
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "some-request-id",
+            "seatbid": [{
+                "seat": "appnexus",
+                "bid": [{
+                    "id": "apn-bid",
+                    "impid": "my-imp-id",
+                    "price": 0.3,
+                    "w": 200,
+                    "h": 250,
+                    "crid": "creative-1",
+                    "ext": {
+                        "prebid": {
+                            "type": "video"
+                        },
+                        "someField": "someValue",
+                        "origbidcpm": 0.3
+                    }
+                }]
+            }]
+        },
+        "ext": {
+            "prebid": {
+                "passthrough": {"bid_response_passthrough":20}
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/request-ext-prebid-filtering.json b/exchange/exchangetest/request-ext-prebid-filtering.json
new file mode 100644
index 00000000..1d699c8a
--- /dev/null
+++ b/exchange/exchangetest/request-ext-prebid-filtering.json
@@ -0,0 +1,160 @@
+{
+    "description": "Verifies only allowed bid.request.ext.prebid values are passed to the bidder, leaving other ext fields untouched.",
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "test-request-id",
+            "site": {
+                "page": "test.testpage.com"
+            },
+            "imp": [
+                {
+                    "id": "imp-id",
+                    "video": {
+                        "mimes": [
+                            "video/mp4"
+                        ]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
+                    }
+                }
+            ],
+            "ext": {
+                "other": "test-other",
+                "prebid": {
+                    "data": {
+                        "eidpermissions": [
+                            {
+                                "source": "test-source",
+                                "bidders": [
+                                    "appnexus"
+                                ]
+                            }
+                        ]
+                    },
+                    "integration": "test-integration",
+                    "channel": {
+                        "name": "test-name",
+                        "version": "test-version"
+                    },
+                    "debug": true,
+                    "currency": {
+                        "rates": {
+                            "FOO": {
+                                "BAR": 42
+                            }
+                        },
+                        "usepbsrates": true
+                    },
+                    "bidderparams": {
+                        "appnexus": {
+                            "param1": 1,
+                            "paramA": "A"
+                        },
+                        "rubicon": {
+                            "not": "permitted-for-appnexus"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "test-request-id",
+                    "site": {
+                        "page": "test.testpage.com"
+                    },
+                    "imp": [
+                        {
+                            "id": "imp-id",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
+                            }
+                        }
+                    ],
+                    "ext": {
+                        "other": "test-other",
+                        "prebid": {
+                            "integration": "test-integration",
+                            "channel": {
+                                "name": "test-name",
+                                "version": "test-version"
+                            },
+                            "debug": true,
+                            "currency": {
+                                "rates": {
+                                    "FOO": {
+                                        "BAR": 42
+                                    }
+                                },
+                                "usepbsrates": true
+                            },
+                            "bidderparams": {
+                                "param1": 1,
+                                "paramA": "A"
+                            }
+                        }
+                    }
+                }
+            },
+            "mockResponse": {
+                "pbsSeatBids": [
+                    {
+                        "pbsBids": [
+                            {
+                                "ortbBid": {
+                                    "id": "apn-bid",
+                                    "impid": "imp-id",
+                                    "price": 0.3,
+                                    "w": 200,
+                                    "h": 250,
+                                    "crid": "creative-1"
+                                },
+                                "bidType": "video"
+                            }
+                        ],
+                        "seat": "appnexus"
+                    }
+                ]
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "test-request-id",
+            "seatbid": [
+                {
+                    "seat": "appnexus",
+                    "bid": [
+                        {
+                            "id": "apn-bid",
+                            "impid": "imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "origbidcpm": 0.3,
+                                "prebid": {
+                                    "type": "video"
+                                }
+                            }
+                        }
+                    ]
+                }
+            ]
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/request-imp-ext-prebid-filtering.json b/exchange/exchangetest/request-imp-ext-prebid-filtering.json
new file mode 100644
index 00000000..fb8e0892
--- /dev/null
+++ b/exchange/exchangetest/request-imp-ext-prebid-filtering.json
@@ -0,0 +1,136 @@
+{
+    "description": "Verifies only allowed bid.request.imp[].ext.prebid values are passed to the bidder, dropping other fields.",
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "test-request-id",
+            "site": {
+                "page": "test.testpage.com"
+            },
+            "imp": [
+                {
+                    "id": "imp-id",
+                    "video": {
+                        "mimes": [
+                            "video/mp4"
+                        ]
+                    },
+                    "ext": {
+                        "prebid": {
+                            "bidder": {
+                                "appnexus": {
+                                    "placementId": 1
+                                }
+                            },
+                            "storedrequest": {
+                                "id": "any-id"
+                            },
+                            "storedauctionresponse": {
+                                "id": "any-id"
+                            },
+                            "storedbidresponse": [
+                                {
+                                    "id": "any-id",
+                                    "bidder": "foo"
+                                }
+                            ],
+                            "is_rewarded_inventory": true,
+                            "options": {
+                                "echovideoattrs": true
+                            },
+                            "unknown": "any-unknown"
+                        },
+                        "data": "any-data",
+                        "context": "any-context",
+                        "skadn": "any-skadn",
+                        "gpid": "any-gpid",
+                        "tid": "any-tid"
+                    }
+                }
+            ]
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "test-request-id",
+                    "site": {
+                        "page": "test.testpage.com"
+                    },
+                    "imp": [
+                        {
+                            "id": "imp-id",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                },
+                                "prebid": {
+                                    "is_rewarded_inventory": true,
+                                    "options": {
+                                        "echovideoattrs": true
+                                    }
+                                },
+                                "data": "any-data",
+                                "context": "any-context",
+                                "skadn": "any-skadn",
+                                "gpid": "any-gpid",
+                                "tid": "any-tid"
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "pbsSeatBids": [
+                    {
+                        "pbsBids": [
+                            {
+                                "ortbBid": {
+                                    "id": "apn-bid",
+                                    "impid": "imp-id",
+                                    "price": 0.3,
+                                    "w": 200,
+                                    "h": 250,
+                                    "crid": "creative-1"
+                                },
+                                "bidType": "video"
+                            }
+                        ],
+                        "seat": "appnexus"
+                    }
+                ]
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "test-request-id",
+            "seatbid": [
+                {
+                    "seat": "appnexus",
+                    "bid": [
+                        {
+                            "id": "apn-bid",
+                            "impid": "imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "origbidcpm": 0.3,
+                                "prebid": {
+                                    "type": "video"
+                                }
+                            }
+                        }
+                    ]
+                }
+            ]
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/schain-host-and-request.json b/exchange/exchangetest/schain-host-and-request.json
index 7a071124..88f407cd 100644
--- a/exchange/exchangetest/schain-host-and-request.json
+++ b/exchange/exchangetest/schain-host-and-request.json
@@ -6,33 +6,39 @@
             "site": {
                 "page": "test.somepage.com"
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "appnexus": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }],
+            ],
             "ext": {
                 "prebid": {
                     "bidadjustmentfactors": null,
-                    "schains": [{
-                        "bidders": ["appnexus"],
-                        "schain": {
-                            "complete": 1,
-                            "nodes": [{
-                                "asi": "whatever.com",
-                                "sid": "1234",
-                                "rid": "123-456-7890",
-                                "hp": 1
-                            }],
-                            "ver": "2.0"
+                    "schains": [
+                        {
+                            "bidders": ["appnexus"],
+                            "schain": {
+                                "complete": 1,
+                                "nodes": [
+                                    {
+                                        "asi": "whatever.com",
+                                        "sid": "1234",
+                                        "rid": "123-456-7890",
+                                        "hp": 1
+                                    }
+                                ],
+                                "ver": "2.0"
+                            }
                         }
-                    }],
+                    ],
                     "debug": true,
                     "nosale": ["appnexus"]
                 }
@@ -47,21 +53,22 @@
                     "site": {
                         "page": "test.somepage.com"
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }],
+                    ],
                     "ext": {
                         "prebid": {
-                            "debug": true,
-                            "nosale": ["appnexus"]
+                            "debug": true
                         }
                     },
                     "source": {
@@ -69,21 +76,21 @@
                             "schain": {
                                 "complete": 1,
                                 "nodes": [
-                                  {
-                                    "asi": "whatever.com",
-                                    "sid": "1234",
-                                    "rid": "123-456-7890",
-                                    "hp": 1
-                                  },
-                                  {
-                                    "asi": "pbshostcompany.com",
-                                    "sid": "00001",
-                                    "rid": "BidRequest",
-                                    "hp": 1
-                                  }
+                                    {
+                                        "asi": "whatever.com",
+                                        "sid": "1234",
+                                        "rid": "123-456-7890",
+                                        "hp": 1
+                                    },
+                                    {
+                                        "asi": "pbshostcompany.com",
+                                        "sid": "00001",
+                                        "rid": "BidRequest",
+                                        "hp": 1
+                                    }
                                 ],
                                 "ver": "2.0"
-                              }
+                            }
                         }
                     }
                 },
diff --git a/exchange/exchangetest/schain-host-only.json b/exchange/exchangetest/schain-host-only.json
index 1750a8b4..d58947e3 100644
--- a/exchange/exchangetest/schain-host-only.json
+++ b/exchange/exchangetest/schain-host-only.json
@@ -6,17 +6,19 @@
             "site": {
                 "page": "test.somepage.com"
             },
-            "imp": [{
-                "id": "my-imp-id",
-                "video": {
-                    "mimes": ["video/mp4"]
-                },
-                "ext": {
-                    "appnexus": {
-                        "placementId": 1
+            "imp": [
+                {
+                    "id": "my-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"]
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "placementId": 1
+                        }
                     }
                 }
-            }],
+            ],
             "ext": {
                 "prebid": {
                     "debug": true,
@@ -33,21 +35,22 @@
                     "site": {
                         "page": "test.somepage.com"
                     },
-                    "imp": [{
-                        "id": "my-imp-id",
-                        "video": {
-                            "mimes": ["video/mp4"]
-                        },
-                        "ext": {
-                            "bidder": {
-                                "placementId": 1
+                    "imp": [
+                        {
+                            "id": "my-imp-id",
+                            "video": {
+                                "mimes": ["video/mp4"]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": 1
+                                }
                             }
                         }
-                    }],
+                    ],
                     "ext": {
                         "prebid": {
-                            "debug": true,
-                            "nosale": ["appnexus"]
+                            "debug": true
                         }
                     },
                     "source": {
@@ -55,15 +58,15 @@
                             "schain": {
                                 "complete": 0,
                                 "nodes": [
-                                  {
-                                    "asi": "pbshostcompany.com",
-                                    "sid": "00001",
-                                    "rid": "BidRequest",
-                                    "hp": 1
-                                  }
+                                    {
+                                        "asi": "pbshostcompany.com",
+                                        "sid": "00001",
+                                        "rid": "BidRequest",
+                                        "hp": 1
+                                    }
                                 ],
                                 "ver": "1.0"
-                              }
+                            }
                         }
                     }
                 },
diff --git a/exchange/exchangetest/tricky-userids.json b/exchange/exchangetest/tricky-userids.json
index e01f53c7..065ec812 100644
--- a/exchange/exchangetest/tricky-userids.json
+++ b/exchange/exchangetest/tricky-userids.json
@@ -73,11 +73,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              }
-            }
+            "prebid": {}
           }
         }
       },
@@ -111,11 +107,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              }
-            }
+            "prebid": {}
           }
         }
       },
@@ -147,11 +139,7 @@
             }
           ],
           "ext": {
-            "prebid": {
-              "aliases": {
-                "districtm": "appnexus"
-              }
-            }
+            "prebid": {}
           }
         }
       },
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 600d0721..4ff2aa0a 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -265,13 +265,14 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 			expectedError:     "",
 		},
 		{
-			description: "imp.ext.prebid - Bidders Only",
+			description: "imp.ext.prebid - Bidder Only",
 			givenImpExt: map[string]json.RawMessage{
 				"prebid":  json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder": json.RawMessage(`"anyBidder"`),
@@ -281,28 +282,55 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			expectedError: "",
 		},
 		{
-			description: "imp.ext.prebid - Bidders + Other Values",
+			description: "imp.ext.prebid - Bidder + Other Forbidden Value",
 			givenImpExt: map[string]json.RawMessage{
 				"prebid":  json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder":    json.RawMessage(`"anyBidder"`),
-				"someOther": json.RawMessage(`"value"`),
+				"forbidden": json.RawMessage(`"anyValue"`),
 			},
 			expected: map[string]json.RawMessage{
-				"prebid":  json.RawMessage(`{"someOther":"value"}`),
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "imp.ext.prebid - Bidder + Other Allowed Values",
+			givenImpExt: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"data":    json.RawMessage(`"anyData"`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"bidder":                json.RawMessage(`"anyBidder"`),
+				"is_rewarded_inventory": json.RawMessage(`"anyIsRewardedInventory"`),
+				"options":               json.RawMessage(`"anyOptions"`),
+			},
+			expected: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`{"is_rewarded_inventory":"anyIsRewardedInventory","options":"anyOptions"}`),
+				"data":    json.RawMessage(`"anyData"`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			expectedError: "",
 		},
@@ -314,6 +342,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"context":   json.RawMessage(`"anyContext"`),
 				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":      json.RawMessage(`"anyGPID"`),
+				"tid":       json.RawMessage(`"anyTID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{},
 			expected: map[string]json.RawMessage{
@@ -321,11 +350,12 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			expectedError: "",
 		},
 		{
-			description: "imp.ext + imp.ext.prebid - Prebid Bidders Only",
+			description: "imp.ext + imp.ext.prebid - Prebid Bidder Only",
 			givenImpExt: map[string]json.RawMessage{
 				"anyBidder": json.RawMessage(`"anyBidderValues"`),
 				"prebid":    json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
@@ -333,6 +363,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"context":   json.RawMessage(`"anyContext"`),
 				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":      json.RawMessage(`"anyGPID"`),
+				"tid":       json.RawMessage(`"anyTID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder": json.RawMessage(`"anyBidder"`),
@@ -342,11 +373,12 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			expectedError: "",
 		},
 		{
-			description: "imp.ext + imp.ext.prebid - Prebid Bidders + Other Values",
+			description: "imp.ext + imp.ext.prebid - Prebid Bidder + Other Forbidden Value",
 			givenImpExt: map[string]json.RawMessage{
 				"anyBidder": json.RawMessage(`"anyBidderValues"`),
 				"prebid":    json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
@@ -358,10 +390,35 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder":    json.RawMessage(`"anyBidder"`),
-				"someOther": json.RawMessage(`"value"`),
+				"forbidden": json.RawMessage(`"anyValue"`),
+			},
+			expected: map[string]json.RawMessage{
+				"data":    json.RawMessage(`"anyData"`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "imp.ext + imp.ext.prebid - Prebid Bidder + Other Allowed Values",
+			givenImpExt: map[string]json.RawMessage{
+				"anyBidder": json.RawMessage(`"anyBidderValues"`),
+				"prebid":    json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"data":      json.RawMessage(`"anyData"`),
+				"context":   json.RawMessage(`"anyContext"`),
+				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":      json.RawMessage(`"anyGPID"`),
+				"tid":       json.RawMessage(`"anyTID"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"bidder":                json.RawMessage(`"anyBidder"`),
+				"is_rewarded_inventory": json.RawMessage(`"anyIsRewardedInventory"`),
+				"options":               json.RawMessage(`"anyOptions"`),
 			},
 			expected: map[string]json.RawMessage{
-				"prebid":  json.RawMessage(`{"someOther":"value"}`),
+				"prebid":  json.RawMessage(`{"is_rewarded_inventory":"anyIsRewardedInventory","options":"anyOptions"}`),
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
@@ -378,12 +435,13 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
 				"gpid":    json.RawMessage(`"anyGPID"`),
+				"tid":     json.RawMessage(`"anyTID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
-				"malformed": json.RawMessage(`json`), // String value without quotes.
+				"options": json.RawMessage(`malformed`), // String value without quotes.
 			},
 			expected:      nil,
-			expectedError: "cannot marshal ext.prebid: json: error calling MarshalJSON for type json.RawMessage: invalid character 'j' looking for beginning of value",
+			expectedError: "cannot marshal ext.prebid: json: error calling MarshalJSON for type json.RawMessage: invalid character 'm' looking for beginning of value",
 		},
 	}
 
@@ -2382,6 +2440,99 @@ func TestCleanOpenRTBRequestsGDPRBlockBidRequest(t *testing.T) {
 	}
 }
 
+func TestBuildRequestExtForBidder(t *testing.T) {
+	bidder := "foo"
+	bidderParams := json.RawMessage(`"bar"`)
+
+	testCases := []struct {
+		description  string
+		requestExt   json.RawMessage
+		bidderParams map[string]json.RawMessage
+		expectedJson json.RawMessage
+	}{
+		{
+			description:  "Nil",
+			bidderParams: nil,
+			requestExt:   nil,
+			expectedJson: json.RawMessage(``),
+		},
+		{
+			description:  "Empty",
+			bidderParams: nil,
+			requestExt:   json.RawMessage(`{}`),
+			expectedJson: json.RawMessage(`{"prebid":{}}`),
+		},
+		{
+			description:  "Prebid - Allowed Fields Only",
+			bidderParams: nil,
+			requestExt:   json.RawMessage(`{"prebid":{"integration":"a","channel":{"name":"b","version":"c"},"debug":true,"currency":{"rates":{"FOO":{"BAR":42}},"usepbsrates":true}}}`),
+			expectedJson: json.RawMessage(`{"prebid":{"integration":"a","channel":{"name":"b","version":"c"},"debug":true,"currency":{"rates":{"FOO":{"BAR":42}},"usepbsrates":true}}}`),
+		},
+		{
+			description:  "Prebid - Allowed Fields + Bidder Params",
+			bidderParams: map[string]json.RawMessage{bidder: bidderParams},
+			requestExt:   json.RawMessage(`{"prebid":{"integration":"a","channel":{"name":"b","version":"c"},"debug":true,"currency":{"rates":{"FOO":{"BAR":42}},"usepbsrates":true}}}`),
+			expectedJson: json.RawMessage(`{"prebid":{"integration":"a","channel":{"name":"b","version":"c"},"debug":true,"currency":{"rates":{"FOO":{"BAR":42}},"usepbsrates":true},"bidderparams":"bar"}}`),
+		},
+		{
+			description:  "Other",
+			bidderParams: nil,
+			requestExt:   json.RawMessage(`{"other":"foo"}`),
+			expectedJson: json.RawMessage(`{"other":"foo","prebid":{}}`),
+		},
+		{
+			description:  "Prebid + Other + Bider Params",
+			bidderParams: map[string]json.RawMessage{bidder: bidderParams},
+			requestExt:   json.RawMessage(`{"other":"foo","prebid":{"integration":"a","channel":{"name":"b","version":"c"},"debug":true,"currency":{"rates":{"FOO":{"BAR":42}},"usepbsrates":true}}}`),
+			expectedJson: json.RawMessage(`{"other":"foo","prebid":{"integration":"a","channel":{"name":"b","version":"c"},"debug":true,"currency":{"rates":{"FOO":{"BAR":42}},"usepbsrates":true},"bidderparams":"bar"}}`),
+		},
+	}
+
+	for _, test := range testCases {
+		requestExtParsed := &openrtb_ext.ExtRequest{}
+		if test.requestExt != nil {
+			err := json.Unmarshal(test.requestExt, requestExtParsed)
+			if !assert.NoError(t, err, test.description+":parse_ext") {
+				continue
+			}
+		}
+
+		actualJson, actualErr := buildRequestExtForBidder(bidder, test.requestExt, requestExtParsed, test.bidderParams)
+		if len(test.expectedJson) > 0 {
+			assert.JSONEq(t, string(test.expectedJson), string(actualJson), test.description+":json")
+		} else {
+			assert.Equal(t, test.expectedJson, actualJson, test.description+":json")
+		}
+		assert.NoError(t, actualErr, test.description+":err")
+	}
+}
+
+func TestBuildRequestExtForBidder_RequestExtParsedNil(t *testing.T) {
+	var (
+		bidder           = "foo"
+		requestExt       = json.RawMessage(`{}`)
+		requestExtParsed *openrtb_ext.ExtRequest
+		bidderParams     map[string]json.RawMessage
+	)
+
+	actualJson, actualErr := buildRequestExtForBidder(bidder, requestExt, requestExtParsed, bidderParams)
+	assert.Equal(t, json.RawMessage(``), actualJson)
+	assert.NoError(t, actualErr)
+}
+
+func TestBuildRequestExtForBidder_RequestExtMalformed(t *testing.T) {
+	var (
+		bidder           = "foo"
+		requestExt       = json.RawMessage(`malformed`)
+		requestExtParsed = &openrtb_ext.ExtRequest{}
+		bidderParams     map[string]json.RawMessage
+	)
+
+	actualJson, actualErr := buildRequestExtForBidder(bidder, requestExt, requestExtParsed, bidderParams)
+	assert.Equal(t, json.RawMessage(nil), actualJson)
+	assert.EqualError(t, actualErr, "invalid character 'm' looking for beginning of value")
+}
+
 // newAdapterAliasBidRequest builds a BidRequest with aliases
 func newAdapterAliasBidRequest(t *testing.T) *openrtb2.BidRequest {
 	dnt := int8(1)