Repository: prebid/prebid-server
Pull request #2948 (2023-07-19 06:27:04)

Use bidder name instead of syncer key
Redirect urls for bidders user sync now have `bidder={bidderName}` not `bidder={syncerKey}`. 

`user_sync` endpoint now returns urls with redirect urls with bidder name instead of syncer key. 
`setuid` endpoint now accepts bidder name, not syncer key: `setuid?bidder=appnexus` not `setuid?bidder=adnxs`
`getuids` endpoint returns ids by syncer key.




Patch:
diff --git a/adapters/adnuntius/adnuntius.go b/adapters/adnuntius/adnuntius.go
index 21830deb..3f91d740 100644
--- a/adapters/adnuntius/adnuntius.go
+++ b/adapters/adnuntius/adnuntius.go
@@ -27,31 +27,35 @@ type adnAdunit struct {
 	AuId       string    `json:"auId"`
 	TargetId   string    `json:"targetId"`
 	Dimensions [][]int64 `json:"dimensions,omitempty"`
+	MaxDeals   int       `json:"maxDeals,omitempty"`
 }
 
 type extDeviceAdnuntius struct {
 	NoCookies bool `json:"noCookies,omitempty"`
 }
 
+type Ad struct {
+	Bid struct {
+		Amount   float64
+		Currency string
+	}
+	DealID          string `json:"dealId,omitempty"`
+	AdId            string
+	CreativeWidth   string
+	CreativeHeight  string
+	CreativeId      string
+	LineItemId      string
+	Html            string
+	DestinationUrls map[string]string
+}
+
 type AdUnit struct {
 	AuId       string
 	TargetId   string
 	Html       string
 	ResponseId string
-	Ads        []struct {
-		Bid struct {
-			Amount   float64
-			Currency string
-		}
-		DealID          string `json:"dealId,omitempty"`
-		AdId            string
-		CreativeWidth   string
-		CreativeHeight  string
-		CreativeId      string
-		LineItemId      string
-		Html            string
-		DestinationUrls map[string]string
-	}
+	Ads        []Ad
+	Deals      []Ad `json:"deals,omitempty"`
 }
 
 type AdnResponse struct {
@@ -213,13 +217,17 @@ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters
 			network = adnuntiusExt.Network
 		}
 
+		adUnit := adnAdunit{
+			AuId:       adnuntiusExt.Auid,
+			TargetId:   fmt.Sprintf("%s-%s", adnuntiusExt.Auid, imp.ID),
+			Dimensions: getImpSizes(imp),
+		}
+		if adnuntiusExt.MaxDeals > 0 {
+			adUnit.MaxDeals = adnuntiusExt.MaxDeals
+		}
 		networkAdunitMap[network] = append(
 			networkAdunitMap[network],
-			adnAdunit{
-				AuId:       adnuntiusExt.Auid,
-				TargetId:   fmt.Sprintf("%s-%s", adnuntiusExt.Auid, imp.ID),
-				Dimensions: getImpSizes(imp),
-			})
+			adUnit)
 	}
 
 	endpoint, err := makeEndpointUrl(ortbRequest, a, noCookies)
@@ -320,6 +328,46 @@ func getGDPR(request *openrtb2.BidRequest) (string, string, error) {
 	return gdpr, consent, nil
 }
 
+func generateAdResponse(ad Ad, impId string, html string, request *openrtb2.BidRequest) (*openrtb2.Bid, []error) {
+
+	creativeWidth, widthErr := strconv.ParseInt(ad.CreativeWidth, 10, 64)
+	if widthErr != nil {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Value of width: %s is not a string", ad.CreativeWidth),
+		}}
+	}
+
+	creativeHeight, heightErr := strconv.ParseInt(ad.CreativeHeight, 10, 64)
+	if heightErr != nil {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Value of height: %s is not a string", ad.CreativeHeight),
+		}}
+	}
+
+	adDomain := []string{}
+	for _, url := range ad.DestinationUrls {
+		domainArray := strings.Split(url, "/")
+		domain := strings.Replace(domainArray[2], "www.", "", -1)
+		adDomain = append(adDomain, domain)
+	}
+
+	bid := openrtb2.Bid{
+		ID:      ad.AdId,
+		ImpID:   impId,
+		W:       creativeWidth,
+		H:       creativeHeight,
+		AdID:    ad.AdId,
+		DealID:  ad.DealID,
+		CID:     ad.LineItemId,
+		CrID:    ad.CreativeId,
+		Price:   ad.Bid.Amount * 1000,
+		AdM:     html,
+		ADomain: adDomain,
+	}
+	return &bid, nil
+
+}
+
 func generateBidResponse(adnResponse *AdnResponse, request *openrtb2.BidRequest) (*adapters.BidderResponse, []error) {
 	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(adnResponse.AdUnits))
 	var currency string
@@ -344,48 +392,34 @@ func generateBidResponse(adnResponse *AdnResponse, request *openrtb2.BidRequest)
 		if len(adunit.Ads) > 0 {
 
 			ad := adunit.Ads[0]
-
 			currency = ad.Bid.Currency
 
-			creativeWidth, widthErr := strconv.ParseInt(ad.CreativeWidth, 10, 64)
-			if widthErr != nil {
+			adBid, err := generateAdResponse(ad, request.Imp[i].ID, adunit.Html, request)
+			if err != nil {
 				return nil, []error{&errortypes.BadInput{
-					Message: fmt.Sprintf("Value of width: %s is not a string", ad.CreativeWidth),
+					Message: fmt.Sprintf("Error at ad generation"),
 				}}
 			}
 
-			creativeHeight, heightErr := strconv.ParseInt(ad.CreativeHeight, 10, 64)
-			if heightErr != nil {
-				return nil, []error{&errortypes.BadInput{
-					Message: fmt.Sprintf("Value of height: %s is not a string", ad.CreativeHeight),
-				}}
-			}
-
-			adDomain := []string{}
-			for _, url := range ad.DestinationUrls {
-				domainArray := strings.Split(url, "/")
-				domain := strings.Replace(domainArray[2], "www.", "", -1)
-				adDomain = append(adDomain, domain)
-			}
-
-			bid := openrtb2.Bid{
-				ID:      ad.AdId,
-				ImpID:   request.Imp[i].ID,
-				W:       creativeWidth,
-				H:       creativeHeight,
-				AdID:    ad.AdId,
-				DealID:  ad.DealID,
-				CID:     ad.LineItemId,
-				CrID:    ad.CreativeId,
-				Price:   ad.Bid.Amount * 1000,
-				AdM:     adunit.Html,
-				ADomain: adDomain,
-			}
-
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
-				Bid:     &bid,
+				Bid:     adBid,
 				BidType: "banner",
 			})
+
+			for _, deal := range adunit.Deals {
+				dealBid, err := generateAdResponse(deal, request.Imp[i].ID, deal.Html, request)
+				if err != nil {
+					return nil, []error{&errortypes.BadInput{
+						Message: fmt.Sprintf("Error at ad generation"),
+					}}
+				}
+
+				bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+					Bid:     dealBid,
+					BidType: "banner",
+				})
+			}
+
 		}
 
 	}
diff --git a/adapters/brightroll/brightroll.go b/adapters/brightroll/brightroll.go
deleted file mode 100644
index a917fe87..00000000
--- a/adapters/brightroll/brightroll.go
+++ /dev/null
@@ -1,263 +0,0 @@
-package brightroll
-
-import (
-	"encoding/json"
-	"fmt"
-	"net/http"
-	"strconv"
-
-	"github.com/prebid/openrtb/v19/adcom1"
-	"github.com/prebid/openrtb/v19/openrtb2"
-	"github.com/prebid/prebid-server/adapters"
-	"github.com/prebid/prebid-server/config"
-	"github.com/prebid/prebid-server/errortypes"
-	"github.com/prebid/prebid-server/openrtb_ext"
-)
-
-type BrightrollAdapter struct {
-	URI       string
-	extraInfo ExtraInfo
-}
-
-type ExtraInfo struct {
-	Accounts []Account `json:"accounts"`
-}
-
-type Account struct {
-	ID       string   `json:"id"`
-	Badv     []string `json:"badv"`
-	Bcat     []string `json:"bcat"`
-	Battr    []int8   `json:"battr"`
-	BidFloor float64  `json:"bidfloor"`
-}
-
-func (a *BrightrollAdapter) MakeRequests(requestIn *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
-
-	request := *requestIn
-	errs := make([]error, 0, len(request.Imp))
-	if len(request.Imp) == 0 {
-		err := &errortypes.BadInput{
-			Message: "No impression in the bid request",
-		}
-		errs = append(errs, err)
-		return nil, errs
-	}
-
-	errors := make([]error, 0, 1)
-
-	var bidderExt adapters.ExtImpBidder
-	err := json.Unmarshal(request.Imp[0].Ext, &bidderExt)
-	if err != nil {
-		err = &errortypes.BadInput{
-			Message: "ext.bidder not provided",
-		}
-		errors = append(errors, err)
-		return nil, errors
-	}
-	var brightrollExt openrtb_ext.ExtImpBrightroll
-	err = json.Unmarshal(bidderExt.Bidder, &brightrollExt)
-	if err != nil {
-		err = &errortypes.BadInput{
-			Message: "ext.bidder.publisher not provided",
-		}
-		errors = append(errors, err)
-		return nil, errors
-	}
-	if brightrollExt.Publisher == "" {
-		err = &errortypes.BadInput{
-			Message: "publisher is empty",
-		}
-		errors = append(errors, err)
-		return nil, errors
-	}
-
-	var account *Account
-	for _, a := range a.extraInfo.Accounts {
-		if a.ID == brightrollExt.Publisher {
-			account = &a
-			break
-		}
-	}
-
-	if account == nil {
-		err = &errortypes.BadInput{
-			Message: "Invalid publisher",
-		}
-		errors = append(errors, err)
-		return nil, errors
-	}
-
-	validImpExists := false
-	for i := 0; i < len(request.Imp); i++ {
-		//Brightroll supports only banner and video impressions as of now
-		if request.Imp[i].Banner != nil {
-			bannerCopy := *request.Imp[i].Banner
-			if bannerCopy.W == nil && bannerCopy.H == nil && len(bannerCopy.Format) > 0 {
-				firstFormat := bannerCopy.Format[0]
-				bannerCopy.W = &(firstFormat.W)
-				bannerCopy.H = &(firstFormat.H)
-			}
-
-			if len(account.Battr) > 0 {
-				bannerCopy.BAttr = getBlockedCreativetypes(account.Battr)
-			}
-			request.Imp[i].Banner = &bannerCopy
-			validImpExists = true
-		} else if request.Imp[i].Video != nil {
-			validImpExists = true
-			if brightrollExt.Publisher == "adthrive" {
-				videoCopy := *request.Imp[i].Video
-				if len(account.Battr) > 0 {
-					videoCopy.BAttr = getBlockedCreativetypes(account.Battr)
-				}
-				request.Imp[i].Video = &videoCopy
-			}
-		}
-		if validImpExists && request.Imp[i].BidFloor == 0 && account.BidFloor > 0 {
-			request.Imp[i].BidFloor = account.BidFloor
-		}
-	}
-	if !validImpExists {
-		err := &errortypes.BadInput{
-			Message: fmt.Sprintf("No valid impression in the bid request"),
-		}
-		errs = append(errs, err)
-		return nil, errs
-	}
-
-	request.AT = 1 //Defaulting to first price auction for all prebid requests
-
-	if len(account.Bcat) > 0 {
-		request.BCat = account.Bcat
-	}
-
-	if len(account.Badv) > 0 {
-		request.BAdv = account.Badv
-	}
-	reqJSON, err := json.Marshal(request)
-	if err != nil {
-		errs = append(errs, err)
-		return nil, errs
-	}
-	thisURI := a.URI
-	thisURI = thisURI + "?publisher=" + brightrollExt.Publisher
-	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 request.Device != nil {
-		addHeaderIfNonEmpty(headers, "User-Agent", request.Device.UA)
-		addHeaderIfNonEmpty(headers, "X-Forwarded-For", request.Device.IP)
-		addHeaderIfNonEmpty(headers, "Accept-Language", request.Device.Language)
-		if request.Device.DNT != nil {
-			addHeaderIfNonEmpty(headers, "DNT", strconv.Itoa(int(*request.Device.DNT)))
-		}
-	}
-
-	return []*adapters.RequestData{{
-		Method:  "POST",
-		Uri:     thisURI,
-		Body:    reqJSON,
-		Headers: headers,
-	}}, errors
-}
-
-func (a *BrightrollAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []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. ", 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{&errortypes.BadServerResponse{
-			Message: fmt.Sprintf("bad server response: %d. ", err),
-		}}
-	}
-
-	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid))
-	sb := bidResp.SeatBid[0]
-	for i := 0; i < len(sb.Bid); i++ {
-		bid := sb.Bid[i]
-		bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
-			Bid:     &bid,
-			BidType: getMediaTypeForImp(bid.ImpID, internalRequest.Imp),
-		})
-	}
-	return bidResponse, nil
-}
-
-func getBlockedCreativetypes(attr []int8) []adcom1.CreativeAttribute {
-	var creativeAttr []adcom1.CreativeAttribute
-	for i := 0; i < len(attr); i++ {
-		creativeAttr = append(creativeAttr, adcom1.CreativeAttribute(attr[i]))
-	}
-	return creativeAttr
-}
-
-// Adding header fields to request header
-func addHeaderIfNonEmpty(headers http.Header, headerName string, headerValue string) {
-	if len(headerValue) > 0 {
-		headers.Add(headerName, headerValue)
-	}
-}
-
-// getMediaTypeForImp figures out which media type this bid is for.
-func getMediaTypeForImp(impId string, imps []openrtb2.Imp) openrtb_ext.BidType {
-	mediaType := openrtb_ext.BidTypeBanner //default type
-	for _, imp := range imps {
-		if imp.ID == impId {
-			if imp.Video != nil {
-				mediaType = openrtb_ext.BidTypeVideo
-			}
-			return mediaType
-		}
-	}
-	return mediaType
-}
-
-// Builder builds a new instance of the Brightroll adapter for the given bidder with the given config.
-func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
-	extraInfo, err := getExtraInfo(config.ExtraAdapterInfo)
-	if err != nil {
-		return nil, err
-	}
-
-	bidder := &BrightrollAdapter{
-		URI:       config.Endpoint,
-		extraInfo: extraInfo,
-	}
-	return bidder, nil
-}
-
-func getExtraInfo(v string) (ExtraInfo, error) {
-	if len(v) == 0 {
-		return getDefaultExtraInfo(), nil
-	}
-
-	var extraInfo ExtraInfo
-	if err := json.Unmarshal([]byte(v), &extraInfo); err != nil {
-		return extraInfo, fmt.Errorf("invalid extra info: %v", err)
-	}
-
-	return extraInfo, nil
-}
-
-func getDefaultExtraInfo() ExtraInfo {
-	return ExtraInfo{
-		Accounts: []Account{},
-	}
-}
diff --git a/adapters/mobilefuse/mobilefuse.go b/adapters/mobilefuse/mobilefuse.go
index 07ecd61b..c13dbe8a 100644
--- a/adapters/mobilefuse/mobilefuse.go
+++ b/adapters/mobilefuse/mobilefuse.go
@@ -100,19 +100,16 @@ func (adapter *MobileFuseAdapter) makeRequest(bidRequest *openrtb2.BidRequest) (
 	var errs []error
 
 	mobileFuseExtension, errs := getFirstMobileFuseExtension(bidRequest)
-
 	if errs != nil {
 		return nil, errs
 	}
 
 	endpoint, err := adapter.getEndpoint(mobileFuseExtension)
-
 	if err != nil {
 		return nil, append(errs, err)
 	}
 
 	validImps, err := getValidImps(bidRequest, mobileFuseExtension)
-
 	if err != nil {
 		errs = append(errs, err)
 		return nil, errs
@@ -121,7 +118,6 @@ func (adapter *MobileFuseAdapter) makeRequest(bidRequest *openrtb2.BidRequest) (
 	mobileFuseBidRequest := *bidRequest
 	mobileFuseBidRequest.Imp = validImps
 	body, err := json.Marshal(mobileFuseBidRequest)
-
 	if err != nil {
 		return nil, append(errs, err)
 	}
@@ -165,13 +161,23 @@ func getFirstMobileFuseExtension(request *openrtb2.BidRequest) (*openrtb_ext.Ext
 	return &mobileFuseImpExtension, errs
 }
 
+func getMobileFuseExtensionForImp(imp *openrtb2.Imp, mobileFuseImpExtension *openrtb_ext.ExtImpMobileFuse) error {
+	var bidder_imp_extension adapters.ExtImpBidder
+
+	err := json.Unmarshal(imp.Ext, &bidder_imp_extension)
+	if err != nil {
+		return err
+	}
+
+	return json.Unmarshal(bidder_imp_extension.Bidder, &mobileFuseImpExtension)
+}
+
 func (adapter *MobileFuseAdapter) getEndpoint(ext *openrtb_ext.ExtImpMobileFuse) (string, error) {
 	publisher_id := strconv.Itoa(ext.PublisherId)
 
-	url, errs := macros.ResolveMacros(adapter.EndpointTemplate, macros.EndpointTemplateParams{PublisherID: publisher_id})
-
-	if errs != nil {
-		return "", errs
+	url, err := macros.ResolveMacros(adapter.EndpointTemplate, macros.EndpointTemplateParams{PublisherID: publisher_id})
+	if err != nil {
+		return "", err
 	}
 
 	if ext.TagidSrc == "ext" {
@@ -186,10 +192,15 @@ func getValidImps(bidRequest *openrtb2.BidRequest, ext *openrtb_ext.ExtImpMobile
 
 	for _, imp := range bidRequest.Imp {
 		if imp.Banner != nil || imp.Video != nil || imp.Native != nil {
+			err := getMobileFuseExtensionForImp(&imp, ext)
+			if err != nil {
+				return nil, err
+			}
+
 			imp.TagID = strconv.Itoa(ext.PlacementId)
 
 			var extSkadn ExtSkadn
-			err := json.Unmarshal(imp.Ext, &extSkadn)
+			err = json.Unmarshal(imp.Ext, &extSkadn)
 			if err != nil {
 				return nil, err
 			}
@@ -204,8 +215,6 @@ func getValidImps(bidRequest *openrtb2.BidRequest, ext *openrtb_ext.ExtImpMobile
 			}
 
 			validImps = append(validImps, imp)
-
-			break
 		}
 	}
 
diff --git a/adapters/orbidder/orbidder.go b/adapters/orbidder/orbidder.go
index 43c3574b..b4f1a16c 100644
--- a/adapters/orbidder/orbidder.go
+++ b/adapters/orbidder/orbidder.go
@@ -125,19 +125,51 @@ func (rcv OrbidderAdapter) MakeBids(_ *openrtb2.BidRequest, _ *adapters.RequestD
 		return nil, []error{err}
 	}
 
+	var bidErrs []error
 	bidResponse := adapters.NewBidderResponseWithBidsCapacity(5)
 	for _, seatBid := range bidResp.SeatBid {
-		for _, bid := range seatBid.Bid {
+		for i := range seatBid.Bid {
+			// later we have to add the bid as a pointer,
+			// because of this we need a variable that only exists at this loop iteration.
+			// otherwise there will be issues with multibid and pointer behavior.
+			bid := seatBid.Bid[i]
+			bidType, err := getBidType(bid)
+			if err != nil {
+				// could not determinate media type, append an error and continue with the next bid.
+				bidErrs = append(bidErrs, err)
+				continue
+			}
+
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
 				Bid:     &bid,
-				BidType: openrtb_ext.BidTypeBanner,
+				BidType: bidType,
 			})
 		}
 	}
 	if bidResp.Cur != "" {
 		bidResponse.Currency = bidResp.Cur
 	}
-	return bidResponse, nil
+
+	return bidResponse, bidErrs
+}
+
+func getBidType(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+
+	// determinate media type by bid response field mtype
+	switch bid.MType {
+	case openrtb2.MarkupBanner:
+		return openrtb_ext.BidTypeBanner, nil
+	case openrtb2.MarkupVideo:
+		return openrtb_ext.BidTypeVideo, nil
+	case openrtb2.MarkupAudio:
+		return openrtb_ext.BidTypeAudio, nil
+	case openrtb2.MarkupNative:
+		return openrtb_ext.BidTypeNative, nil
+	}
+
+	return "", &errortypes.BadInput{
+		Message: fmt.Sprintf("Could not define media type for impression: %s", bid.ImpID),
+	}
 }
 
 // Builder builds a new instance of the Orbidder adapter for the given bidder with the given config.
diff --git a/adapters/ownadx/ownadx.go b/adapters/ownadx/ownadx.go
new file mode 100644
index 00000000..c19343ba
--- /dev/null
+++ b/adapters/ownadx/ownadx.go
@@ -0,0 +1,213 @@
+package ownadx
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/prebid/openrtb/v19/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/macros"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"net/http"
+	"text/template"
+)
+
+type adapter struct {
+	endpoint *template.Template
+}
+type bidExt struct {
+	MediaType string `json:"mediaType"`
+}
+
+func (adapter *adapter) getRequestData(bidRequest *openrtb2.BidRequest, impExt *openrtb_ext.ExtImpOwnAdx, imps []openrtb2.Imp) (*adapters.RequestData, error) {
+	pbidRequest := createBidRequest(bidRequest, imps)
+	reqJSON, err := json.Marshal(pbidRequest)
+	if err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "Prebid bidder request not valid or can't be marshalled. Err: " + err.Error(),
+		}
+	}
+	url, err := adapter.buildEndpointURL(impExt)
+	if err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "Error while creating endpoint. Err: " + err.Error(),
+		}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("x-openrtb-version", "2.5")
+
+	return &adapters.RequestData{
+		Method:  "POST",
+		Uri:     url,
+		Body:    reqJSON,
+		Headers: headers}, nil
+
+}
+func createBidRequest(rtbBidRequest *openrtb2.BidRequest, imps []openrtb2.Imp) *openrtb2.BidRequest {
+	bidRequest := *rtbBidRequest
+	bidRequest.Imp = imps
+	return &bidRequest
+}
+func (adapter *adapter) buildEndpointURL(params *openrtb_ext.ExtImpOwnAdx) (string, error) {
+	endpointParams := macros.EndpointTemplateParams{
+		ZoneID:    params.SspId,
+		AccountID: params.SeatId,
+		SourceId:  params.TokenId,
+	}
+	return macros.ResolveMacros(adapter.endpoint, endpointParams)
+}
+
+func getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpOwnAdx, error) {
+	var bidderExt adapters.ExtImpBidder
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "Bidder extension not valid or can't be unmarshalled",
+		}
+	}
+
+	var ownAdxExt openrtb_ext.ExtImpOwnAdx
+	if err := json.Unmarshal(bidderExt.Bidder, &ownAdxExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "Error while unmarshaling bidder extension",
+		}
+	}
+
+	return &ownAdxExt, nil
+}
+
+func (adapter *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+
+	errs := make([]error, 0, len(request.Imp))
+	if len(request.Imp) == 0 {
+		errs = append(errs, &errortypes.BadInput{
+			Message: "No impression in the bid request"},
+		)
+		return nil, errs
+	}
+	extImps, errors := groupImpsByExt(request.Imp)
+	if len(errors) != 0 {
+		errs = append(errs, errors...)
+	}
+	if len(extImps) == 0 {
+		return nil, errs
+	}
+	reqDetail := make([]*adapters.RequestData, 0, len(extImps))
+	for k, imps := range extImps {
+		bidRequest, err := adapter.getRequestData(request, &k, imps)
+		if err != nil {
+			errs = append(errs, err)
+		} else {
+			reqDetail = append(reqDetail, bidRequest)
+		}
+	}
+	return reqDetail, errs
+}
+func groupImpsByExt(imps []openrtb2.Imp) (map[openrtb_ext.ExtImpOwnAdx][]openrtb2.Imp, []error) {
+	respExt := make(map[openrtb_ext.ExtImpOwnAdx][]openrtb2.Imp)
+	errors := make([]error, 0, len(imps))
+	for _, imp := range imps {
+		ownAdxExt, err := getImpressionExt(&(imp))
+		if err != nil {
+			errors = append(errors, err)
+			continue
+		}
+
+		respExt[*ownAdxExt] = append(respExt[*ownAdxExt], imp)
+	}
+	return respExt, errors
+}
+
+func (adapter *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+	if response.StatusCode == http.StatusBadRequest {
+		return nil, []error{
+			&errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Bad request: %d", response.StatusCode),
+			},
+		}
+	}
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{
+			&errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Unexpected status code: %d. Run with request.test = 1 for more info.", response.StatusCode),
+			},
+		}
+	}
+	var bidResp openrtb2.BidResponse
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{
+			&errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Bad server response "),
+			},
+		}
+	}
+	if len(bidResp.SeatBid) == 0 {
+		return nil, []error{
+			&errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Array SeatBid cannot be empty "),
+			},
+		}
+	}
+
+	seatBid := bidResp.SeatBid[0]
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid))
+	if len(seatBid.Bid) == 0 {
+		return nil, []error{
+			&errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Bid cannot be empty "),
+			},
+		}
+	}
+	for i := 0; i < len(seatBid.Bid); i++ {
+		var bidType openrtb_ext.BidType
+		bid := seatBid.Bid[i]
+
+		bidType, err := getMediaType(bid)
+		if err != nil {
+			return nil, []error{&errortypes.BadServerResponse{
+				Message: "Bid type is invalid",
+			}}
+		}
+		bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+			Bid:     &bid,
+			BidType: bidType,
+		})
+	}
+
+	return bidResponse, nil
+}
+
+// Builder builds a new instance of the OwnAdx adapter for the given bidder with the given config
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	template, err := template.New("endpointTemplate").Parse(config.Endpoint)
+	if err != nil {
+		return nil, fmt.Errorf("unable to parse endpoint url template: %v", err)
+	}
+
+	bidder := &adapter{
+		endpoint: template,
+	}
+
+	return bidder, nil
+}
+
+func getMediaType(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+	switch bid.MType {
+	case openrtb2.MarkupBanner:
+		return openrtb_ext.BidTypeBanner, nil
+	case openrtb2.MarkupVideo:
+		return openrtb_ext.BidTypeVideo, nil
+	case openrtb2.MarkupAudio:
+		return openrtb_ext.BidTypeAudio, nil
+	case openrtb2.MarkupNative:
+		return openrtb_ext.BidTypeNative, nil
+	default:
+		return "", fmt.Errorf("invalid BidType: %d", bid.MType)
+	}
+}
diff --git a/adapters/rtbhouse/rtbhouse.go b/adapters/rtbhouse/rtbhouse.go
index c8afb0c4..dc67df9a 100644
--- a/adapters/rtbhouse/rtbhouse.go
+++ b/adapters/rtbhouse/rtbhouse.go
@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"net/http"
+	"strings"
 
 	"github.com/prebid/openrtb/v19/openrtb2"
 	"github.com/prebid/prebid-server/adapters"
@@ -12,6 +13,15 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
+const (
+	BidderCurrency string = "USD"
+)
+
+// RTBHouseAdapter implements the Bidder interface.
+type RTBHouseAdapter struct {
+	endpoint string
+}
+
 // Builder builds a new instance of the RTBHouse adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
 	bidder := &RTBHouseAdapter{
@@ -20,11 +30,6 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co
 	return bidder, nil
 }
 
-// RTBHouseAdapter implements the Bidder interface.
-type RTBHouseAdapter struct {
-	endpoint string
-}
-
 // MakeRequests prepares the HTTP requests which should be made to fetch bids.
 func (adapter *RTBHouseAdapter) MakeRequests(
 	openRTBRequest *openrtb2.BidRequest,
@@ -33,7 +38,48 @@ func (adapter *RTBHouseAdapter) MakeRequests(
 	requestsToBidder []*adapters.RequestData,
 	errs []error,
 ) {
-	openRTBRequestJSON, err := json.Marshal(openRTBRequest)
+
+	reqCopy := *openRTBRequest
+	reqCopy.Imp = []openrtb2.Imp{}
+	for _, imp := range openRTBRequest.Imp {
+		var bidFloorCur = imp.BidFloorCur
+		var bidFloor = imp.BidFloor
+		if bidFloorCur == "" && bidFloor == 0 {
+			rtbhouseExt, err := getImpressionExt(imp)
+			if err != nil {
+				return nil, []error{err}
+			}
+			if rtbhouseExt.BidFloor > 0 && len(reqCopy.Cur) > 0 {
+				bidFloorCur = reqCopy.Cur[0]
+				bidFloor = rtbhouseExt.BidFloor
+			}
+		}
+
+		// Check if imp comes with bid floor amount defined in a foreign currency
+		if bidFloor > 0 && bidFloorCur != "" && strings.ToUpper(bidFloorCur) != BidderCurrency {
+			// Convert to US dollars
+			convertedValue, err := reqInfo.ConvertCurrency(bidFloor, bidFloorCur, BidderCurrency)
+			if err != nil {
+				return nil, []error{err}
+			}
+
+			bidFloorCur = BidderCurrency
+			bidFloor = convertedValue
+		}
+
+		if bidFloor > 0 && bidFloorCur == BidderCurrency {
+			// Update after conversion. All imp elements inside request.Imp are shallow copies
+			// therefore, their non-pointer values are not shared memory and are safe to modify.
+			imp.BidFloorCur = bidFloorCur
+			imp.BidFloor = bidFloor
+		}
+
+		// Set the CUR of bid to BIDDER_CURRENCY after converting all floors
+		reqCopy.Cur = []string{BidderCurrency}
+		reqCopy.Imp = append(reqCopy.Imp, imp)
+	}
+
+	openRTBRequestJSON, err := json.Marshal(reqCopy)
 	if err != nil {
 		errs = append(errs, err)
 		return nil, errs
@@ -52,6 +98,24 @@ func (adapter *RTBHouseAdapter) MakeRequests(
 	return requestsToBidder, errs
 }
 
+func getImpressionExt(imp openrtb2.Imp) (*openrtb_ext.ExtImpRTBHouse, error) {
+	var bidderExt adapters.ExtImpBidder
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "Bidder extension not provided or can't be unmarshalled",
+		}
+	}
+
+	var rtbhouseExt openrtb_ext.ExtImpRTBHouse
+	if err := json.Unmarshal(bidderExt.Bidder, &rtbhouseExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "Error while unmarshaling bidder extension",
+		}
+	}
+
+	return &rtbhouseExt, nil
+}
+
 const unexpectedStatusCodeFormat = "" +
 	"Unexpected status code: %d. Run with request.debug = 1 for more info"
 
@@ -97,6 +161,8 @@ func (adapter *RTBHouseAdapter) MakeBids(
 		}
 	}
 
+	bidderResponse.Currency = BidderCurrency
+
 	return bidderResponse, nil
 
 }
diff --git a/adapters/vox/vox.go b/adapters/vox/vox.go
new file mode 100644
index 00000000..0b56fcbf
--- /dev/null
+++ b/adapters/vox/vox.go
@@ -0,0 +1,86 @@
+package vox
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/prebid/openrtb/v19/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	endpoint string
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	requestJSON, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	requestData := &adapters.RequestData{
+		Method: "POST",
+		Uri:    a.endpoint,
+		Body:   requestJSON,
+	}
+
+	return []*adapters.RequestData{requestData}, nil
+}
+
+func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if adapters.IsResponseStatusCodeNoContent(responseData) {
+		return nil, nil
+	}
+
+	if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil {
+		return nil, []error{err}
+	}
+
+	var response openrtb2.BidResponse
+	if err := json.Unmarshal(responseData.Body, &response); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
+	bidResponse.Currency = response.Cur
+
+	for _, seatBid := range response.SeatBid {
+		for i, bid := range seatBid.Bid {
+			bidType, err := getMediaTypeForBid(bid)
+			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 getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+	switch bid.MType {
+	case openrtb2.MarkupBanner:
+		return openrtb_ext.BidTypeBanner, nil
+	case openrtb2.MarkupVideo:
+		return openrtb_ext.BidTypeVideo, nil
+	case openrtb2.MarkupAudio:
+		return openrtb_ext.BidTypeAudio, nil
+	case openrtb2.MarkupNative:
+		return openrtb_ext.BidTypeNative, nil
+	default:
+		return "", fmt.Errorf("Unable to fetch mediaType in multi-format: %s", bid.ImpID)
+	}
+}
diff --git a/config/bidderinfo.go b/config/bidderinfo.go
index 6f62488c..630952a6 100644
--- a/config/bidderinfo.go
+++ b/config/bidderinfo.go
@@ -23,6 +23,7 @@ type BidderInfos map[string]BidderInfo
 
 // BidderInfo specifies all configuration for a bidder except for enabled status, endpoint, and extra information.
 type BidderInfo struct {
+	AliasOf          string `yaml:"aliasOf" mapstructure:"aliasOf"`
 	Disabled         bool   `yaml:"disabled" mapstructure:"disabled"`
 	Endpoint         string `yaml:"endpoint" mapstructure:"endpoint"`
 	ExtraAdapterInfo string `yaml:"extra_info" mapstructure:"extra_info"`
@@ -161,7 +162,7 @@ type SyncerEndpoint struct {
 	// startup:
 	//
 	//  {{.ExternalURL}} - This will be replaced with the host server's externally reachable http path.
-	//  {{.SyncerKey}}   - This will be replaced with the syncer key.
+	//  {{.BidderName}}  - This will be replaced with the bidder name.
 	//  {{.SyncType}}    - This will be replaced with the sync type, either 'b' for iframe syncs or 'i'
 	//                     for redirect/image syncs.
 	//  {{.UserMacro}}   - This will be replaced with the bidder server's user id macro.
@@ -266,20 +267,35 @@ func (infos BidderInfos) validate(errs []error) []error {
 		if bidder.IsEnabled() {
 			errs = validateAdapterEndpoint(bidder.Endpoint, bidderName, errs)
 
-			validateInfoErr := validateInfo(bidder, bidderName)
-			if validateInfoErr != nil {
-				errs = append(errs, validateInfoErr)
+			if err := validateInfo(bidder, bidderName); err != nil {
+				errs = append(errs, err)
 			}
 
-			validateSyncerErr := validateSyncer(bidder)
-			if validateSyncerErr != nil {
-				errs = append(errs, validateSyncerErr)
+			if err := validateSyncer(bidder); err != nil {
+				errs = append(errs, err)
+			}
+
+			if err := validateAliases(bidder, infos, bidderName); err != nil {
+				errs = append(errs, err)
 			}
 		}
 	}
 	return errs
 }
 
+func validateAliases(bidder BidderInfo, infos BidderInfos, bidderName string) error {
+	if len(bidder.AliasOf) > 0 {
+		if parentBidder, ok := infos[bidder.AliasOf]; ok {
+			if len(parentBidder.AliasOf) > 0 {
+				return fmt.Errorf("bidder: %s cannot be an alias of an alias: %s", bidder.AliasOf, bidderName)
+			}
+		} else {
+			return fmt.Errorf("bidder: %s not found for an alias: %s", bidder.AliasOf, bidderName)
+		}
+	}
+	return nil
+}
+
 var testEndpointTemplateParams = macros.EndpointTemplateParams{
 	Host:        "anyHost",
 	PublisherID: "anyPublisherID",
diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go
index 9324b15d..0d5c35f9 100644
--- a/endpoints/openrtb2/amp_auction.go
+++ b/endpoints/openrtb2/amp_auction.go
@@ -69,6 +69,7 @@ func NewAmpEndpoint(
 	bidderMap map[string]openrtb_ext.BidderName,
 	storedRespFetcher stored_requests.Fetcher,
 	hookExecutionPlanBuilder hooks.ExecutionPlanBuilder,
+	tmaxAdjustments *exchange.TmaxAdjustmentsPreprocessed,
 ) (httprouter.Handle, error) {
 
 	if ex == nil || validator == nil || requestsById == nil || accounts == nil || cfg == nil || metricsEngine == nil {
@@ -100,7 +101,9 @@ func NewAmpEndpoint(
 		nil,
 		ipValidator,
 		storedRespFetcher,
-		hookExecutionPlanBuilder}).AmpAuction), nil
+		hookExecutionPlanBuilder,
+		tmaxAdjustments,
+	}).AmpAuction), nil
 
 }
 
@@ -251,9 +254,15 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
 		QueryParams:                r.URL.Query(),
 		TCF2Config:                 tcf2Config,
 		Activities:                 activities,
+		TmaxAdjustments:            deps.tmaxAdjustments,
 	}
 
 	auctionResponse, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
+	defer func() {
+		if !auctionRequest.BidderResponseStartTime.IsZero() {
+			deps.metricsEngine.RecordOverheadTime(metrics.MakeAuctionResponse, time.Since(auctionRequest.BidderResponseStartTime))
+		}
+	}()
 	var response *openrtb2.BidResponse
 	if auctionResponse != nil {
 		response = auctionResponse.BidResponse
@@ -287,6 +296,9 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
 	}
 
 	labels, ao = sendAmpResponse(w, hookExecutor, auctionResponse, reqWrapper, account, labels, ao, errL)
+	if len(ao.Errors) == 0 && !auctionRequest.BidderResponseStartTime.IsZero() {
+		deps.metricsEngine.RecordOverheadTime(metrics.MakeAuctionResponse, time.Since(auctionRequest.BidderResponseStartTime))
+	}
 }
 
 func rejectAmpRequest(
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 9a0d0d07..8e01552c 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -92,6 +92,7 @@ func NewEndpoint(
 	bidderMap map[string]openrtb_ext.BidderName,
 	storedRespFetcher stored_requests.Fetcher,
 	hookExecutionPlanBuilder hooks.ExecutionPlanBuilder,
+	tmaxAdjustments *exchange.TmaxAdjustmentsPreprocessed,
 ) (httprouter.Handle, error) {
 	if ex == nil || validator == nil || requestsById == nil || accounts == nil || cfg == nil || metricsEngine == nil {
 		return nil, errors.New("NewEndpoint requires non-nil arguments.")
@@ -122,7 +123,8 @@ func NewEndpoint(
 		nil,
 		ipValidator,
 		storedRespFetcher,
-		hookExecutionPlanBuilder}).Auction), nil
+		hookExecutionPlanBuilder,
+		tmaxAdjustments}).Auction), nil
 }
 
 type endpointDeps struct {
@@ -144,6 +146,7 @@ type endpointDeps struct {
 	privateNetworkIPValidator iputil.IPValidator
 	storedRespFetcher         stored_requests.Fetcher
 	hookExecutionPlanBuilder  hooks.ExecutionPlanBuilder
+	tmaxAdjustments           *exchange.TmaxAdjustmentsPreprocessed
 }
 
 func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
@@ -250,8 +253,14 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
 		HookExecutor:               hookExecutor,
 		TCF2Config:                 tcf2Config,
 		Activities:                 activities,
+		TmaxAdjustments:            deps.tmaxAdjustments,
 	}
 	auctionResponse, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
+	defer func() {
+		if !auctionRequest.BidderResponseStartTime.IsZero() {
+			deps.metricsEngine.RecordOverheadTime(metrics.MakeAuctionResponse, time.Since(auctionRequest.BidderResponseStartTime))
+		}
+	}()
 	ao.RequestWrapper = req
 	ao.Account = account
 	var response *openrtb2.BidResponse
@@ -283,6 +292,9 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
 		glog.Errorf("Error setting seat non-bid: %v", err)
 	}
 	labels, ao = sendAuctionResponse(w, hookExecutor, response, req.BidRequest, account, labels, ao)
+	if len(ao.Errors) == 0 && !auctionRequest.BidderResponseStartTime.IsZero() {
+		deps.metricsEngine.RecordOverheadTime(metrics.MakeAuctionResponse, time.Since(auctionRequest.BidderResponseStartTime))
+	}
 }
 
 // setSeatNonBidRaw is transitional function for setting SeatNonBid inside bidResponse.Ext
diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go
index 872ea2bd..a2a1e03e 100644
--- a/endpoints/openrtb2/video_auction.go
+++ b/endpoints/openrtb2/video_auction.go
@@ -56,6 +56,7 @@ func NewVideoEndpoint(
 	defReqJSON []byte,
 	bidderMap map[string]openrtb_ext.BidderName,
 	cache prebid_cache_client.Client,
+	tmaxAdjustments *exchange.TmaxAdjustmentsPreprocessed,
 ) (httprouter.Handle, error) {
 
 	if ex == nil || validator == nil || requestsById == nil || accounts == nil || cfg == nil || met == nil {
@@ -89,7 +90,8 @@ func NewVideoEndpoint(
 		videoEndpointRegexp,
 		ipValidator,
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{}}).VideoAuctionEndpoint), nil
+		hooks.EmptyPlanBuilder{},
+		tmaxAdjustments}).VideoAuctionEndpoint), nil
 }
 
 /*
@@ -311,9 +313,15 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
 		GlobalPrivacyControlHeader: secGPC,
 		PubID:                      labels.PubID,
 		HookExecutor:               hookexecution.EmptyHookExecutor{},
+		TmaxAdjustments:            deps.tmaxAdjustments,
 	}
 
 	auctionResponse, err := deps.ex.HoldAuction(ctx, auctionRequest, &debugLog)
+	defer func() {
+		if !auctionRequest.BidderResponseStartTime.IsZero() {
+			deps.metricsEngine.RecordOverheadTime(metrics.MakeAuctionResponse, time.Since(auctionRequest.BidderResponseStartTime))
+		}
+	}()
 	vo.RequestWrapper = bidReqWrapper
 	var response *openrtb2.BidResponse
 	if auctionResponse != nil {
@@ -367,6 +375,10 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
 		return
 	}
 
+	if len(vo.Errors) == 0 && !auctionRequest.BidderResponseStartTime.IsZero() {
+		deps.metricsEngine.RecordOverheadTime(metrics.MakeAuctionResponse, time.Since(auctionRequest.BidderResponseStartTime))
+	}
+
 	w.Header().Set("Content-Type", "application/json")
 	w.Write(resp)
 
diff --git a/endpoints/setuid.go b/endpoints/setuid.go
index 905fa26b..25fb2465 100644
--- a/endpoints/setuid.go
+++ b/endpoints/setuid.go
@@ -39,13 +39,6 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 	encoder := usersync.Base64Encoder{}
 	decoder := usersync.Base64Decoder{}
 
-	// convert map of syncers by bidder to map of syncers by key
-	// - its safe to assume that if multiple bidders map to the same key, the syncers are interchangeable.
-	syncersByKey := make(map[string]usersync.Syncer, len(syncersByBidder))
-	for _, v := range syncersByBidder {
-		syncersByKey[v.Key()] = v
-	}
-
 	return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
 		so := analytics.SetUIDObject{
 			Status: http.StatusOK,
@@ -65,7 +58,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 
 		query := r.URL.Query()
 
-		syncer, err := getSyncer(query, syncersByKey)
+		syncer, err := getSyncer(query, syncersByBidder)
 		if err != nil {
 			w.WriteHeader(http.StatusBadRequest)
 			w.Write([]byte(err.Error()))
@@ -313,14 +306,14 @@ func parseConsentFromGppStr(gppQueryValue string) (string, error) {
 	return gdprConsent, nil
 }
 
-func getSyncer(query url.Values, syncersByKey map[string]usersync.Syncer) (usersync.Syncer, error) {
-	key := query.Get("bidder")
+func getSyncer(query url.Values, syncersByBidder map[string]usersync.Syncer) (usersync.Syncer, error) {
+	bidder := query.Get("bidder")
 
-	if key == "" {
+	if bidder == "" {
 		return nil, errors.New(`"bidder" query param is required`)
 	}
 
-	syncer, syncerExists := syncersByKey[key]
+	syncer, syncerExists := syncersByBidder[bidder]
 	if !syncerExists {
 		return nil, errors.New("The bidder name provided is not supported by Prebid Server")
 	}
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index f8344525..a1038d71 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -56,7 +56,6 @@ import (
 	"github.com/prebid/prebid-server/adapters/bmtm"
 	"github.com/prebid/prebid-server/adapters/boldwin"
 	"github.com/prebid/prebid-server/adapters/brave"
-	"github.com/prebid/prebid-server/adapters/brightroll"
 	"github.com/prebid/prebid-server/adapters/ccx"
 	"github.com/prebid/prebid-server/adapters/coinzilla"
 	"github.com/prebid/prebid-server/adapters/colossus"
@@ -128,6 +127,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/operaads"
 	"github.com/prebid/prebid-server/adapters/orbidder"
 	"github.com/prebid/prebid-server/adapters/outbrain"
+	"github.com/prebid/prebid-server/adapters/ownadx"
 	"github.com/prebid/prebid-server/adapters/pangle"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
 	"github.com/prebid/prebid-server/adapters/pubnative"
@@ -169,6 +169,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/vidoomy"
 	"github.com/prebid/prebid-server/adapters/visiblemeasures"
 	"github.com/prebid/prebid-server/adapters/visx"
+	"github.com/prebid/prebid-server/adapters/vox"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
 	"github.com/prebid/prebid-server/adapters/xeworks"
 	"github.com/prebid/prebid-server/adapters/yahooAds"
@@ -242,7 +243,6 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderBmtm:              bmtm.Builder,
 		openrtb_ext.BidderBoldwin:           boldwin.Builder,
 		openrtb_ext.BidderBrave:             brave.Builder,
-		openrtb_ext.BidderBrightroll:        brightroll.Builder,
 		openrtb_ext.BidderCcx:               ccx.Builder,
 		openrtb_ext.BidderCoinzilla:         coinzilla.Builder,
 		openrtb_ext.BidderColossus:          colossus.Builder,
@@ -321,6 +321,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderOperaads:          operaads.Builder,
 		openrtb_ext.BidderOrbidder:          orbidder.Builder,
 		openrtb_ext.BidderOutbrain:          outbrain.Builder,
+		openrtb_ext.BidderOwnAdx:            ownadx.Builder,
 		openrtb_ext.BidderPangle:            pangle.Builder,
 		openrtb_ext.BidderPGAM:              adtelligent.Builder,
 		openrtb_ext.BidderPubmatic:          pubmatic.Builder,
@@ -369,6 +370,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderViewdeos:          adtelligent.Builder,
 		openrtb_ext.BidderVisibleMeasures:   visiblemeasures.Builder,
 		openrtb_ext.BidderVisx:              visx.Builder,
+		openrtb_ext.BidderVox:               vox.Builder,
 		openrtb_ext.BidderVrtcal:            vrtcal.Builder,
 		openrtb_ext.BidderXeworks:           xeworks.Builder,
 		openrtb_ext.BidderYahooAds:          yahooAds.Builder,
diff --git a/exchange/adapter_util.go b/exchange/adapter_util.go
index ad1866a6..624a22ce 100644
--- a/exchange/adapter_util.go
+++ b/exchange/adapter_util.go
@@ -33,6 +33,10 @@ func buildBidders(infos config.BidderInfos, builders map[openrtb_ext.BidderName]
 	var errs []error
 
 	for bidder, info := range infos {
+		if len(info.AliasOf) > 0 {
+			errs = append(errs, fmt.Errorf("This feature is currently under development"))
+			continue
+		}
 		bidderName, bidderNameFound := openrtb_ext.NormalizeBidderName(bidder)
 		if !bidderNameFound {
 			errs = append(errs, fmt.Errorf("%v: unknown bidder", bidder))
@@ -93,6 +97,7 @@ func GetDisabledBiddersErrorMessages(infos config.BidderInfos) map[string]string
 		"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 		"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
 		"verizonmedia":   `Bidder "verizonmedia" is no longer available in Prebid Server. Please update your configuration.`,
+		"brightroll":     `Bidder "brightroll" is no longer available in Prebid Server. Please update your configuration.`,
 	}
 
 	for name, info := range infos {
diff --git a/exchange/bidder.go b/exchange/bidder.go
index 27012ff4..5d9d5cba 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -67,6 +67,7 @@ type bidRequestOptions struct {
 	headerDebugAllowed  bool
 	addCallSignHeader   bool
 	bidAdjustments      map[string]float64
+	tmaxAdjustments     *TmaxAdjustmentsPreprocessed
 }
 
 type extraBidderRespInfo struct {
@@ -143,6 +144,11 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, bidderRequest Bidde
 	//check if real request exists for this bidder or it only has stored responses
 	dataLen := 0
 	if len(bidderRequest.BidRequest.Imp) > 0 {
+		// Reducing the amount of time bidders have to compensate for the processing time used by PBS to fetch a stored request (if needed), validate the OpenRTB request and split it into multiple requests sanitized for each bidder
+		// As well as for the time needed by PBS to prepare the auction response
+		if bidRequestOptions.tmaxAdjustments != nil && bidRequestOptions.tmaxAdjustments.IsEnforced {
+			bidderRequest.BidRequest.TMax = getBidderTmax(&bidderTmaxCtx{ctx}, bidderRequest.BidRequest.TMax, *bidRequestOptions.tmaxAdjustments)
+		}
 		reqData, errs = bidder.Bidder.MakeRequests(bidderRequest.BidRequest, reqInfo)
 
 		if len(reqData) == 0 {
diff --git a/exchange/exchange.go b/exchange/exchange.go
index e1a9868d..1436f3ea 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -6,7 +6,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/prebid/prebid-server/privacy"
 	"math/rand"
 	"net/url"
 	"runtime/debug"
@@ -15,6 +14,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/prebid/prebid-server/privacy"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/adservertargeting"
 	"github.com/prebid/prebid-server/bidadjustment"
@@ -205,11 +206,13 @@ type AuctionRequest struct {
 	// map of imp id to stored response
 	StoredAuctionResponses stored_responses.ImpsWithBidResponses
 	// map of imp id to bidder to stored response
-	StoredBidResponses    stored_responses.ImpBidderStoredResp
-	BidderImpReplaceImpID stored_responses.BidderImpReplaceImpID
-	PubID                 string
-	HookExecutor          hookexecution.StageExecutor
-	QueryParams           url.Values
+	StoredBidResponses      stored_responses.ImpBidderStoredResp
+	BidderImpReplaceImpID   stored_responses.BidderImpReplaceImpID
+	PubID                   string
+	HookExecutor            hookexecution.StageExecutor
+	QueryParams             url.Values
+	BidderResponseStartTime time.Time
+	TmaxAdjustments         *TmaxAdjustmentsPreprocessed
 }
 
 // BidderRequest holds the bidder specific request and all other
@@ -367,9 +370,10 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
 			alternateBidderCodes = *r.Account.AlternateBidderCodes
 		}
 		var extraRespInfo extraAuctionResponseInfo
-		adapterBids, adapterExtra, extraRespInfo = e.getAllBids(auctionCtx, bidderRequests, bidAdjustmentFactors, conversions, accountDebugAllow, r.GlobalPrivacyControlHeader, debugLog.DebugOverride, alternateBidderCodes, requestExtLegacy.Prebid.Experiment, r.HookExecutor, r.StartTime, bidAdjustmentRules)
+		adapterBids, adapterExtra, extraRespInfo = e.getAllBids(auctionCtx, bidderRequests, bidAdjustmentFactors, conversions, accountDebugAllow, r.GlobalPrivacyControlHeader, debugLog.DebugOverride, alternateBidderCodes, requestExtLegacy.Prebid.Experiment, r.HookExecutor, r.StartTime, bidAdjustmentRules, r.TmaxAdjustments)
 		fledge = extraRespInfo.fledge
 		anyBidsReturned = extraRespInfo.bidsFound
+		r.BidderResponseStartTime = extraRespInfo.bidderResponseStartTime
 	}
 
 	var (
@@ -658,7 +662,8 @@ func (e *exchange) getAllBids(
 	experiment *openrtb_ext.Experiment,
 	hookExecutor hookexecution.StageExecutor,
 	pbsRequestStartTime time.Time,
-	bidAdjustmentRules map[string][]openrtb_ext.Adjustment) (
+	bidAdjustmentRules map[string][]openrtb_ext.Adjustment,
+	tmaxAdjustments *TmaxAdjustmentsPreprocessed) (
 	map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid,
 	map[openrtb_ext.BidderName]*seatResponseExtra,
 	extraAuctionResponseInfo) {
@@ -697,6 +702,7 @@ func (e *exchange) getAllBids(
 				headerDebugAllowed:  headerDebugAllowed,
 				addCallSignHeader:   isAdsCertEnabled(experiment, e.bidderInfo[string(bidderRequest.BidderName)]),
 				bidAdjustments:      bidAdjustments,
+				tmaxAdjustments:     tmaxAdjustments,
 			}
 			seatBids, extraBidderRespInfo, err := e.adapterMap[bidderRequest.BidderCoreName].requestBid(ctx, bidderRequest, conversions, &reqInfo, e.adsCertSigner, bidReqOptions, alternateBidderCodes, hookExecutor, bidAdjustmentRules)
 			brw.bidderResponseStartTime = extraBidderRespInfo.respProcessingStartTime
diff --git a/exchange/tmax_adjustments.go b/exchange/tmax_adjustments.go
new file mode 100644
index 00000000..86934ecc
--- /dev/null
+++ b/exchange/tmax_adjustments.go
@@ -0,0 +1,57 @@
+package exchange
+
+import (
+	"context"
+	"time"
+
+	"github.com/prebid/prebid-server/config"
+)
+
+type TmaxAdjustmentsPreprocessed struct {
+	BidderNetworkLatencyBuffer     uint
+	PBSResponsePreparationDuration uint
+	BidderResponseDurationMin      uint
+
+	IsEnforced bool
+}
+
+func ProcessTMaxAdjustments(adjustmentsConfig config.TmaxAdjustments) *TmaxAdjustmentsPreprocessed {
+	if !adjustmentsConfig.Enabled {
+		return nil
+	}
+
+	isEnforced := adjustmentsConfig.BidderResponseDurationMin != 0 &&
+		(adjustmentsConfig.BidderNetworkLatencyBuffer != 0 || adjustmentsConfig.PBSResponsePreparationDuration != 0)
+
+	tmax := &TmaxAdjustmentsPreprocessed{
+		BidderNetworkLatencyBuffer:     adjustmentsConfig.BidderNetworkLatencyBuffer,
+		PBSResponsePreparationDuration: adjustmentsConfig.PBSResponsePreparationDuration,
+		BidderResponseDurationMin:      adjustmentsConfig.BidderResponseDurationMin,
+		IsEnforced:                     isEnforced,
+	}
+
+	return tmax
+}
+
+type bidderTmaxContext interface {
+	Deadline() (deadline time.Time, ok bool)
+	RemainingDurationMS(deadline time.Time) int64
+}
+type bidderTmaxCtx struct{ ctx context.Context }
+
+func (b *bidderTmaxCtx) RemainingDurationMS(deadline time.Time) int64 {
+	return time.Until(deadline).Milliseconds()
+}
+func (b *bidderTmaxCtx) Deadline() (deadline time.Time, ok bool) {
+	deadline, ok = b.ctx.Deadline()
+	return
+}
+
+func getBidderTmax(ctx bidderTmaxContext, requestTmaxMS int64, tmaxAdjustments TmaxAdjustmentsPreprocessed) int64 {
+	if tmaxAdjustments.IsEnforced {
+		if deadline, ok := ctx.Deadline(); ok {
+			return ctx.RemainingDurationMS(deadline) - int64(tmaxAdjustments.BidderNetworkLatencyBuffer) - int64(tmaxAdjustments.PBSResponsePreparationDuration)
+		}
+	}
+	return requestTmaxMS
+}
diff --git a/metrics/prometheus/prometheus.go b/metrics/prometheus/prometheus.go
index eb387789..f9d0c4d9 100644
--- a/metrics/prometheus/prometheus.go
+++ b/metrics/prometheus/prometheus.go
@@ -178,7 +178,7 @@ func NewMetrics(cfg config.PrometheusMetrics, disabledMetrics config.DisabledMet
 	cacheWriteTimeBuckets := []float64{0.001, 0.002, 0.005, 0.01, 0.025, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 1}
 	priceBuckets := []float64{250, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000}
 	queuedRequestTimeBuckets := []float64{0, 1, 5, 30, 60, 120, 180, 240, 300}
-	overheadTimeBuckets := []float64{0.00005, 0.0001, 0.0005, 0.001, 0.002, 0.005, 0.01, 0.05}
+	overheadTimeBuckets := []float64{0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1}
 
 	metrics := Metrics{}
 	reg := prometheus.NewRegistry()
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 978af5e0..e9cc81f8 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -142,7 +142,6 @@ const (
 	BidderBmtm              BidderName = "bmtm"
 	BidderBoldwin           BidderName = "boldwin"
 	BidderBrave             BidderName = "brave"
-	BidderBrightroll        BidderName = "brightroll"
 	BidderCcx               BidderName = "ccx"
 	BidderCoinzilla         BidderName = "coinzilla"
 	BidderColossus          BidderName = "colossus"
@@ -221,6 +220,7 @@ const (
 	BidderOperaads          BidderName = "operaads"
 	BidderOrbidder          BidderName = "orbidder"
 	BidderOutbrain          BidderName = "outbrain"
+	BidderOwnAdx            BidderName = "ownadx"
 	BidderPangle            BidderName = "pangle"
 	BidderPGAM              BidderName = "pgam"
 	BidderPubmatic          BidderName = "pubmatic"
@@ -269,6 +269,7 @@ const (
 	BidderViewdeos          BidderName = "viewdeos"
 	BidderVisibleMeasures   BidderName = "visiblemeasures"
 	BidderVisx              BidderName = "visx"
+	BidderVox               BidderName = "vox"
 	BidderVrtcal            BidderName = "vrtcal"
 	BidderXeworks           BidderName = "xeworks"
 	BidderYahooAds          BidderName = "yahooAds"
@@ -341,7 +342,6 @@ func CoreBidderNames() []BidderName {
 		BidderBmtm,
 		BidderBoldwin,
 		BidderBrave,
-		BidderBrightroll,
 		BidderCcx,
 		BidderCoinzilla,
 		BidderColossus,
@@ -420,6 +420,7 @@ func CoreBidderNames() []BidderName {
 		BidderOperaads,
 		BidderOrbidder,
 		BidderOutbrain,
+		BidderOwnAdx,
 		BidderPangle,
 		BidderPGAM,
 		BidderPubmatic,
@@ -468,6 +469,7 @@ func CoreBidderNames() []BidderName {
 		BidderViewdeos,
 		BidderVisibleMeasures,
 		BidderVisx,
+		BidderVox,
 		BidderVrtcal,
 		BidderXeworks,
 		BidderYahooAds,
diff --git a/openrtb_ext/imp_adnuntius.go b/openrtb_ext/imp_adnuntius.go
index b1e41e80..3759ad50 100644
--- a/openrtb_ext/imp_adnuntius.go
+++ b/openrtb_ext/imp_adnuntius.go
@@ -3,5 +3,6 @@ package openrtb_ext
 type ImpExtAdnunitus struct {
 	Auid      string `json:"auId"`
 	Network   string `json:"network"`
-	NoCookies bool   `json:noCookies`
+	NoCookies bool   `json:"noCookies'"`
+	MaxDeals  int    `json:"maxDeals"`
 }
diff --git a/openrtb_ext/imp_brightroll.go b/openrtb_ext/imp_brightroll.go
deleted file mode 100644
index bd42d4aa..00000000
--- a/openrtb_ext/imp_brightroll.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package openrtb_ext
-
-// ExtImpBrightroll defines the contract for bidrequest.imp[i].ext.prebid.bidder.brightroll
-type ExtImpBrightroll struct {
-	Publisher string `json:"publisher"`
-}
diff --git a/openrtb_ext/imp_ownadx.go b/openrtb_ext/imp_ownadx.go
new file mode 100644
index 00000000..caac600b
--- /dev/null
+++ b/openrtb_ext/imp_ownadx.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+type ExtImpOwnAdx struct {
+	SspId   string `json:"sspId"`
+	SeatId  string `json:"seatId"`
+	TokenId string `json:"tokenId"`
+}
diff --git a/openrtb_ext/imp_rtbhouse.go b/openrtb_ext/imp_rtbhouse.go
new file mode 100644
index 00000000..747ea158
--- /dev/null
+++ b/openrtb_ext/imp_rtbhouse.go
@@ -0,0 +1,10 @@
+package openrtb_ext
+
+// ExtImpRTBHouse defines the contract for bidrequest.imp[i].ext.prebid.bidder.rtbhouse
+type ExtImpRTBHouse struct {
+	PublisherId string `json:"publisherId"`
+	Region      string `json:"region"`
+
+	BidFloor float64 `json:"bidfloor,omitempty"`
+	Channel  string  `json:"channel,omitempty"`
+}
diff --git a/openrtb_ext/imp_vox.go b/openrtb_ext/imp_vox.go
new file mode 100644
index 00000000..a6152507
--- /dev/null
+++ b/openrtb_ext/imp_vox.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+type ImpExtVox struct {
+	PlacementID  string   `json:"placementId"`
+	ImageUrl     string   `json:"imageUrl"`
+	DisplaySizes []string `json:"displaySizes"`
+}
diff --git a/router/router.go b/router/router.go
index 8fc99589..12bfbf59 100644
--- a/router/router.go
+++ b/router/router.go
@@ -214,21 +214,22 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R
 		glog.Fatalf("Failed to create ads cert signer: %v", err)
 	}
 
+	tmaxAdjustments := exchange.ProcessTMaxAdjustments(cfg.TmaxAdjustments)
 	planBuilder := hooks.NewExecutionPlanBuilder(cfg.Hooks, repo)
 	macroReplacer := macros.NewStringIndexBasedReplacer()
 	theExchange := exchange.NewExchange(adapters, cacheClient, cfg, syncersByBidder, r.MetricsEngine, cfg.BidderInfos, gdprPermsBuilder, rateConvertor, categoriesFetcher, adsCertSigner, macroReplacer)
 	var uuidGenerator uuidutil.UUIDRandomGenerator
-	openrtbEndpoint, err := openrtb2.NewEndpoint(uuidGenerator, theExchange, paramsValidator, fetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, storedRespFetcher, planBuilder)
+	openrtbEndpoint, err := openrtb2.NewEndpoint(uuidGenerator, theExchange, paramsValidator, fetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, storedRespFetcher, planBuilder, tmaxAdjustments)
 	if err != nil {
 		glog.Fatalf("Failed to create the openrtb2 endpoint handler. %v", err)
 	}
 
-	ampEndpoint, err := openrtb2.NewAmpEndpoint(uuidGenerator, theExchange, paramsValidator, ampFetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, storedRespFetcher, planBuilder)
+	ampEndpoint, err := openrtb2.NewAmpEndpoint(uuidGenerator, theExchange, paramsValidator, ampFetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, storedRespFetcher, planBuilder, tmaxAdjustments)
 	if err != nil {
 		glog.Fatalf("Failed to create the amp endpoint handler. %v", err)
 	}
 
-	videoEndpoint, err := openrtb2.NewVideoEndpoint(uuidGenerator, theExchange, paramsValidator, fetcher, videoFetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, cacheClient)
+	videoEndpoint, err := openrtb2.NewVideoEndpoint(uuidGenerator, theExchange, paramsValidator, fetcher, videoFetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, cacheClient, tmaxAdjustments)
 	if err != nil {
 		glog.Fatalf("Failed to create the video endpoint handler. %v", err)
 	}
diff --git a/server/server.go b/server/server.go
index 31764cc4..9282f0fc 100644
--- a/server/server.go
+++ b/server/server.go
@@ -20,7 +20,7 @@ import (
 
 // Listen blocks forever, serving PBS requests on the given port. This will block forever, until the process is shut down.
 func Listen(cfg *config.Configuration, handler http.Handler, adminHandler http.Handler, metrics *metricsconfig.DetailedMetricsEngine) (err error) {
-	stopSignals := make(chan os.Signal)
+	stopSignals := make(chan os.Signal, 1)
 	signal.Notify(stopSignals, syscall.SIGTERM, syscall.SIGINT)
 
 	// Run the servers. Fan any process-stopper signals out to each server for graceful shutdowns.
diff --git a/static/bidder-info/brightroll.yaml b/static/bidder-info/brightroll.yaml
deleted file mode 100644
index 196344e9..00000000
--- a/static/bidder-info/brightroll.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-endpoint: "http://east-bid.ybp.yahoo.com/bid/appnexuspbs"
-maintainer:
-  email: "dsp-supply-prebid@verizonmedia.com"
-gvlVendorID: 25
-capabilities:
-  app:
-    mediaTypes:
-      - banner
-      - video
-  site:
-    mediaTypes:
-      - banner
-      - video
-userSync:
-  redirect:
-    url: "https://pr-bh.ybp.yahoo.com/sync/appnexusprebidserver/?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url={{.RedirectURL}}"
-    userMacro: "$UID"
diff --git a/static/bidder-info/inmobi.yaml b/static/bidder-info/inmobi.yaml
index ad3562de..72bdd21d 100644
--- a/static/bidder-info/inmobi.yaml
+++ b/static/bidder-info/inmobi.yaml
@@ -1,6 +1,6 @@
 endpoint: "https://api.w.inmobi.com/showad/openrtb/bidder/prebid"
 maintainer:
-  email: "technology-irv@inmobi.com"
+  email: "prebid-support@inmobi.com"
 gvlVendorID: 333
 capabilities:
   app:
diff --git a/static/bidder-info/orbidder.yaml b/static/bidder-info/orbidder.yaml
index b7891af3..705d35a5 100644
--- a/static/bidder-info/orbidder.yaml
+++ b/static/bidder-info/orbidder.yaml
@@ -6,3 +6,7 @@ capabilities:
   app:
     mediaTypes:
       - banner
+  site:
+    mediaTypes:
+      - banner
+      - native
diff --git a/static/bidder-info/ownadx.yaml b/static/bidder-info/ownadx.yaml
new file mode 100644
index 00000000..37567db1
--- /dev/null
+++ b/static/bidder-info/ownadx.yaml
@@ -0,0 +1,12 @@
+endpoint: "https://pbs.prebid-ownadx.com/bidder/bid/{{.AccountID}}/{{.ZoneID}}?token={{.SourceId}}"
+maintainer:
+  email: prebid-team@techbravo.com
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+  site:
+    mediaTypes:
+      - banner
+      - video
diff --git a/static/bidder-info/rtbhouse.yaml b/static/bidder-info/rtbhouse.yaml
index 6a116448..ad2fbfcb 100644
--- a/static/bidder-info/rtbhouse.yaml
+++ b/static/bidder-info/rtbhouse.yaml
@@ -1,6 +1,7 @@
 endpoint: "http://prebidserver-s2s-ams.creativecdn.com/bidder/prebidserver/bids"
 maintainer:
   email: "prebid@rtbhouse.com"
+endpointCompression: gzip
 gvlVendorID: 16
 capabilities:
   site:
diff --git a/static/bidder-info/vox.yaml b/static/bidder-info/vox.yaml
new file mode 100644
index 00000000..e2b5c902
--- /dev/null
+++ b/static/bidder-info/vox.yaml
@@ -0,0 +1,19 @@
+endpoint: "https://ssp.hybrid.ai/prebid/server/v1/auction"
+maintainer:
+  email: prebid@hybrid.ai
+endpointCompression: gzip
+gvlVendorID: 206
+modifyingVastXmlAllowed: true
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+  app:
+    mediaTypes:
+      - banner
+      - video
+userSync:
+  redirect:
+    url: "https://ssp.hybrid.ai/prebid/server/v1/userSync?consent={{.GDPRConsent}}&redirect={{.RedirectURL}}"
+    userMacro: $UID
\ No newline at end of file
diff --git a/static/bidder-params/brightroll.json b/static/bidder-params/brightroll.json
deleted file mode 100644
index 48e48d8a..00000000
--- a/static/bidder-params/brightroll.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "title": "Brightroll Adapter Params",
-  "description": "A schema which validates params accepted by the Brightroll adapter",
-  "type": "object",
-  "properties": {
-      "publisher": {
-        "type": "string",
-        "description": "Publisher Name to use."
-    }
-  },
-  "required": ["publisher"]
-}
diff --git a/static/bidder-params/ownadx.json b/static/bidder-params/ownadx.json
new file mode 100644
index 00000000..f529e74c
--- /dev/null
+++ b/static/bidder-params/ownadx.json
@@ -0,0 +1,27 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "OwnAdx Adapter Params",
+  "description": "A schema which validates params accepted by the OwnAdx adapter",
+  "type": "object",
+
+  "properties": {
+    "sspId": {
+      "type": "string",
+      "description": "Ssp ID"
+    },
+    "seatId": {
+      "type": "string",
+      "description": "Seat ID"
+    },
+    "tokenId": {
+      "type": "string",
+      "description": "Token ID"
+    }
+  },
+
+  "oneOf": [
+    { "required": ["sspId"] },
+    { "required": ["feedId"] },
+    { "required": ["token"] }
+  ]
+}
diff --git a/static/bidder-params/rtbhouse.json b/static/bidder-params/rtbhouse.json
index 00732bed..727f51bc 100644
--- a/static/bidder-params/rtbhouse.json
+++ b/static/bidder-params/rtbhouse.json
@@ -7,6 +7,18 @@
         "publisherId": {
             "type": "string",
             "description": "The publisher’s ID provided by RTB House"
+        },
+        "region": {
+            "type": "string",
+            "description": "The publisher’s assigned datacenter region"
+        },
+        "bidfloor": {
+            "type": "number",
+            "description": "(optional) Minimum bid price in CPM that will be considered"
+        },
+        "channel": {
+            "type": "string",
+            "description": "Inventory channel identifier, limited to 50 characters"
         }
     },
     "required": ["publisherId"]
diff --git a/static/bidder-params/vox.json b/static/bidder-params/vox.json
new file mode 100644
index 00000000..2ae65e99
--- /dev/null
+++ b/static/bidder-params/vox.json
@@ -0,0 +1,27 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Vox Adapter Params",
+  "description": "A schema which validates params accepted by the Vox adapter",
+  "type": "object",
+
+  "properties": {
+    "placementId": {
+      "type": "string",
+      "description": "Placement ID"
+    },
+    "imageUrl": {
+      "type": "string",
+      "description": "An URL of image on which banner should be put(InImage Ad format)."
+    },
+    "displaySizes": {
+      "type": "array",
+      "items": {
+        "type": "string",
+        "description": "<Width>x<Height>(Example: 123x90, 720x100)"
+      },
+      "description": "Display banner sizes which could be shown on top of image."
+    }
+  },
+
+  "required": ["placementId"]
+}
\ No newline at end of file
diff --git a/usersync/syncer.go b/usersync/syncer.go
index 2e0e4102..fb14201f 100644
--- a/usersync/syncer.go
+++ b/usersync/syncer.go
@@ -63,7 +63,7 @@ var ErrSyncerKeyRequired = errors.New("key is required")
 
 // NewSyncer creates a new Syncer from the provided configuration, or return an error if macro substition
 // fails or an endpoint url is invalid.
-func NewSyncer(hostConfig config.UserSync, syncerConfig config.Syncer) (Syncer, error) {
+func NewSyncer(hostConfig config.UserSync, syncerConfig config.Syncer, bidder string) (Syncer, error) {
 	if syncerConfig.Key == "" {
 		return nil, ErrSyncerKeyRequired
 	}
@@ -80,7 +80,7 @@ func NewSyncer(hostConfig config.UserSync, syncerConfig config.Syncer) (Syncer,
 
 	if syncerConfig.IFrame != nil {
 		var err error
-		syncer.iframe, err = buildTemplate(syncerConfig.Key, setuidSyncTypeIFrame, hostConfig, syncerConfig.ExternalURL, *syncerConfig.IFrame)
+		syncer.iframe, err = buildTemplate(bidder, setuidSyncTypeIFrame, hostConfig, syncerConfig.ExternalURL, *syncerConfig.IFrame)
 		if err != nil {
 			return nil, fmt.Errorf("iframe %v", err)
 		}
@@ -91,7 +91,7 @@ func NewSyncer(hostConfig config.UserSync, syncerConfig config.Syncer) (Syncer,
 
 	if syncerConfig.Redirect != nil {
 		var err error
-		syncer.redirect, err = buildTemplate(syncerConfig.Key, setuidSyncTypeRedirect, hostConfig, syncerConfig.ExternalURL, *syncerConfig.Redirect)
+		syncer.redirect, err = buildTemplate(bidder, setuidSyncTypeRedirect, hostConfig, syncerConfig.ExternalURL, *syncerConfig.Redirect)
 		if err != nil {
 			return nil, fmt.Errorf("redirect %v", err)
 		}
@@ -114,13 +114,14 @@ func resolveDefaultSyncType(syncerConfig config.Syncer) SyncType {
 var (
 	macroRegexExternalHost = regexp.MustCompile(`{{\s*\.ExternalURL\s*}}`)
 	macroRegexSyncerKey    = regexp.MustCompile(`{{\s*\.SyncerKey\s*}}`)
+	macroRegexBidderName   = regexp.MustCompile(`{{\s*\.BidderName\s*}}`)
 	macroRegexSyncType     = regexp.MustCompile(`{{\s*\.SyncType\s*}}`)
 	macroRegexUserMacro    = regexp.MustCompile(`{{\s*\.UserMacro\s*}}`)
 	macroRegexRedirect     = regexp.MustCompile(`{{\s*\.RedirectURL\s*}}`)
 	macroRegex             = regexp.MustCompile(`{{\s*\..*?\s*}}`)
 )
 
-func buildTemplate(key, syncTypeValue string, hostConfig config.UserSync, syncerExternalURL string, syncerEndpoint config.SyncerEndpoint) (*template.Template, error) {
+func buildTemplate(bidderName, syncTypeValue string, hostConfig config.UserSync, syncerExternalURL string, syncerEndpoint config.SyncerEndpoint) (*template.Template, error) {
 	redirectTemplate := syncerEndpoint.RedirectURL
 	if redirectTemplate == "" {
 		redirectTemplate = hostConfig.RedirectURL
@@ -128,7 +129,8 @@ func buildTemplate(key, syncTypeValue string, hostConfig config.UserSync, syncer
 
 	externalURL := chooseExternalURL(syncerEndpoint.ExternalURL, syncerExternalURL, hostConfig.ExternalURL)
 
-	redirectURL := macroRegexSyncerKey.ReplaceAllLiteralString(redirectTemplate, key)
+	redirectURL := macroRegexSyncerKey.ReplaceAllLiteralString(redirectTemplate, bidderName)
+	redirectURL = macroRegexBidderName.ReplaceAllLiteralString(redirectURL, bidderName)
 	redirectURL = macroRegexSyncType.ReplaceAllLiteralString(redirectURL, syncTypeValue)
 	redirectURL = macroRegexUserMacro.ReplaceAllLiteralString(redirectURL, syncerEndpoint.UserMacro)
 	redirectURL = macroRegexExternalHost.ReplaceAllLiteralString(redirectURL, externalURL)
@@ -136,7 +138,7 @@ func buildTemplate(key, syncTypeValue string, hostConfig config.UserSync, syncer
 
 	url := macroRegexRedirect.ReplaceAllString(syncerEndpoint.URL, redirectURL)
 
-	templateName := strings.ToLower(key) + "_usersync_url"
+	templateName := strings.ToLower(bidderName) + "_usersync_url"
 	return template.New(templateName).Parse(url)
 }
 
diff --git a/usersync/syncersbuilder.go b/usersync/syncersbuilder.go
index c521d36d..9a52a740 100644
--- a/usersync/syncersbuilder.go
+++ b/usersync/syncersbuilder.go
@@ -59,17 +59,16 @@ func BuildSyncers(hostConfig *config.Configuration, bidderInfos config.BidderInf
 			continue
 		}
 
-		syncer, err := NewSyncer(hostUserSyncConfig, primaryCfg.cfg)
-		if err != nil {
-			errs = append(errs, SyncerBuildError{
-				Bidder:    primaryCfg.name,
-				SyncerKey: key,
-				Err:       err,
-			})
-			continue
-		}
-
 		for _, bidder := range cfgGroup {
+			syncer, err := NewSyncer(hostUserSyncConfig, primaryCfg.cfg, bidder.name)
+			if err != nil {
+				errs = append(errs, SyncerBuildError{
+					Bidder:    primaryCfg.name,
+					SyncerKey: key,
+					Err:       err,
+				})
+				continue
+			}
 			syncers[bidder.name] = syncer
 		}
 	}


Test patch:
diff --git a/adapters/adnuntius/adnuntiustest/supplemental/height-error.json b/adapters/adnuntius/adnuntiustest/supplemental/height-error.json
index 1f213a43..1987fb9d 100644
--- a/adapters/adnuntius/adnuntiustest/supplemental/height-error.json
+++ b/adapters/adnuntius/adnuntiustest/supplemental/height-error.json
@@ -81,7 +81,7 @@
 	],
 	"expectedMakeBidsErrors": [
 		{
-			"value": "json: cannot unmarshal number into Go struct field .AdUnits.Ads.CreativeHeight of type string",
+			"value": "json: cannot unmarshal number into Go struct field Ad.AdUnits.Ads.CreativeHeight of type string",
 			"comparison": "literal"
 		}
 	]
diff --git a/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json b/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json
new file mode 100644
index 00000000..1d4c5bf0
--- /dev/null
+++ b/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json
@@ -0,0 +1,168 @@
+{
+	"mockBidRequest": {
+		"id": "test-request-id",
+		"site": {
+			"page": "prebid.org"
+		},
+		"imp": [
+			{
+				"id": "test-imp-id",
+				"banner": {
+					"format": [
+						{
+							"w": 300,
+							"h": 250
+						},
+						{
+							"w": 300,
+							"h": 600
+						}
+					]
+				},
+				"ext": {
+					"bidder": {
+						"auId": "123",
+						"maxDeals": 2
+					}
+				}
+			}
+		]
+	},
+	
+	"httpCalls": [
+		{
+			"expectedRequest": {
+				"uri": "http://whatever.url?format=json&tzo=0",
+				"body": {
+					"adUnits": [
+						{
+							"auId": "123",
+							"targetId": "123-test-imp-id",
+							"dimensions": [[300,250],[300,600]],
+							"maxDeals": 2
+						}
+					],
+					"context": "prebid.org",
+					"metaData": {}
+				}
+			},
+			"mockResponse": {
+				"status": 200,
+				"body": {
+					"adUnits": [
+						{
+							"auId": "0000000000000123",
+							"targetId": "123-test-imp-id",
+							"html": "<ADCODE>",
+							"matchedAdCount": 1,
+							"responseId": "adn-rsp-815135818",
+							"deals": [
+								{
+									"destinationUrlEsc": "",
+									"clickUrl": "https://click.url",
+									"urls": {
+										"url": "https://delivery.adnuntius.com/c/eKOchNsBJzE.net"
+									},
+									"destinationUrls": {
+										"url": "http://www.google.com"
+									},
+									"cpm": {
+										"amount": 1.0,
+										"currency": "NOK"
+									},
+									"bid": {
+										"amount": 0.001,
+										"currency": "NOK"
+									},
+									"grossBid": {
+										"amount": 0.001,
+										"currency": "NOK"
+									},
+									"netBid": {
+										"amount": 0.001,
+										"currency": "NOK"
+									},
+									"cost": {
+										"amount": 0.001,
+										"currency": "NOK"
+									},
+									"dealId": "deal_123",
+									"adId": "adn-id-116330612",
+									"creativeWidth": "300",
+									"creativeHeight": "250",
+									"creativeId": "dl0knc1lnks9jgvx",
+									"lineItemId": "6l5w2d29kz3vkprq",
+									"layoutId": "adnuntius_image_layout_1",
+									"layoutName": "Image",
+									"layoutExternalReference": "",
+									"html": "<ADCODE>"
+								}
+							],
+							"ads": [
+								{
+									"destinationUrls": {
+										"url": "http://www.google.com"
+									},
+									"bid": {
+										"amount": 0.001,
+										"currency": "NOK"
+									},
+									"adId": "adn-id-1559784095",
+									"creativeWidth": "300",
+									"creativeHeight": "250",
+									"creativeId": "jn9hpzvlsf8cpdmm",
+									"lineItemId": "q7y9qm5b0xt9htrv"
+								}
+							]
+						}
+					],
+					"metaData": {
+						"usi": "5dlpmw0d00btldjdvk1lp8rl",
+						"sessionId": "e4ada7251c93291a871f8e4319cc8fe5"
+					},
+					"duplicateFilter": "AAAAAwAAAAAAJ33PAAAAAAAhrK4AAAAAACYNPAAAAAA=",
+					"segments": [],
+					"keywords": []
+				}
+			}
+		}
+	],
+	"expectedBidResponses": [
+		{
+			"bids": [
+				{
+					"bid": {
+						"id": "adn-id-1559784095",
+						"impid": "test-imp-id",
+						"price": 1,
+						"adm": "<ADCODE>",
+						"adid": "adn-id-1559784095",
+						"adomain": ["google.com"],
+						"cid": "q7y9qm5b0xt9htrv",
+						"crid": "jn9hpzvlsf8cpdmm",
+						"w": 300,
+						"h": 250
+					},
+					"type": "banner"
+				},
+        {
+					"bid": {
+						"id": "adn-id-116330612",
+						"impid": "test-imp-id",
+						"price": 1,
+						"adm": "<ADCODE>",
+						"adid": "adn-id-116330612",
+						"adomain": ["google.com"],
+						"cid": "6l5w2d29kz3vkprq",
+						"crid": "dl0knc1lnks9jgvx",
+						"dealid": "deal_123",
+						"w": 300,
+						"h": 250
+					},
+					"type": "banner"
+				}
+			],
+			"currency": "NOK"
+		}
+	]
+}
diff --git a/adapters/adnuntius/adnuntiustest/supplemental/width-error.json b/adapters/adnuntius/adnuntiustest/supplemental/width-error.json
index 1fd8a83f..4f109942 100644
--- a/adapters/adnuntius/adnuntiustest/supplemental/width-error.json
+++ b/adapters/adnuntius/adnuntiustest/supplemental/width-error.json
@@ -81,7 +81,7 @@
 	],
 	"expectedMakeBidsErrors": [
 		{
-			"value": "json: cannot unmarshal number into Go struct field .AdUnits.Ads.CreativeWidth of type string",
+			"value": "json: cannot unmarshal number into Go struct field Ad.AdUnits.Ads.CreativeWidth of type string",
 			"comparison": "literal"
 		}
 	]
diff --git a/adapters/bidder_test.go b/adapters/bidder_test.go
index f0b833ce..d6373bde 100644
--- a/adapters/bidder_test.go
+++ b/adapters/bidder_test.go
@@ -52,12 +52,12 @@ type mockConversions struct {
 	mock.Mock
 }
 
-func (m mockConversions) GetRate(from string, to string) (float64, error) {
+func (m *mockConversions) GetRate(from string, to string) (float64, error) {
 	args := m.Called(from, to)
 	return args.Get(0).(float64), args.Error(1)
 }
 
-func (m mockConversions) GetRates() *map[string]map[string]float64 {
+func (m *mockConversions) GetRates() *map[string]map[string]float64 {
 	args := m.Called()
 	return args.Get(0).(*map[string]map[string]float64)
 }
diff --git a/adapters/brightroll/brightroll_test.go b/adapters/brightroll/brightroll_test.go
deleted file mode 100644
index 4cf0f46f..00000000
--- a/adapters/brightroll/brightroll_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package brightroll
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/prebid/prebid-server/adapters/adapterstest"
-	"github.com/prebid/prebid-server/config"
-	"github.com/prebid/prebid-server/openrtb_ext"
-)
-
-func TestEmptyConfig(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderBrightroll, config.Adapter{
-		Endpoint:         `http://test-bid.ybp.yahoo.com/bid/appnexuspbs`,
-		ExtraAdapterInfo: ``,
-	}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	ex := ExtraInfo{
-		Accounts: []Account{},
-	}
-	expected := &BrightrollAdapter{
-		URI:       "http://test-bid.ybp.yahoo.com/bid/appnexuspbs",
-		extraInfo: ex,
-	}
-	assert.Equal(t, expected, bidder)
-}
-
-func TestNonEmptyConfig(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderBrightroll, config.Adapter{
-		Endpoint:         `http://test-bid.ybp.yahoo.com/bid/appnexuspbs`,
-		ExtraAdapterInfo: `{"accounts": [{"id": "test","bidfloor":0.1}]}`,
-	}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	ex := ExtraInfo{
-		Accounts: []Account{{ID: "test", BidFloor: 0.1}},
-	}
-	expected := &BrightrollAdapter{
-		URI:       "http://test-bid.ybp.yahoo.com/bid/appnexuspbs",
-		extraInfo: ex,
-	}
-	assert.Equal(t, expected, bidder)
-}
-
-func TestMalformedEmpty(t *testing.T) {
-	_, buildErr := Builder(openrtb_ext.BidderBrightroll, config.Adapter{
-		Endpoint:         `http://test-bid.ybp.yahoo.com/bid/appnexuspbs`,
-		ExtraAdapterInfo: `malformed`,
-	}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
-
-	assert.Error(t, buildErr)
-}
-
-func TestJsonSamples(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderBrightroll, config.Adapter{
-		Endpoint:         `http://test-bid.ybp.yahoo.com/bid/appnexuspbs`,
-		ExtraAdapterInfo: `{"accounts": [{"id": "adthrive","badv": [], "bcat": ["IAB8-5","IAB8-18"],"battr": [1,2,3], "bidfloor":0.0}]}`,
-	}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	adapterstest.RunJSONBidderTest(t, "brightrolltest", bidder)
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/banner-native-audio.json b/adapters/brightroll/brightrolltest/exemplary/banner-native-audio.json
deleted file mode 100644
index f67fa259..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/banner-native-audio.json
+++ /dev/null
@@ -1,169 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      },
-      {
-        "id": "unsupported-native-imp",
-        "native": {
-          "ver": "1.1",
-          "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}"
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      },
-      {
-        "id": "unsupported-audio-imp",
-        "audio": {
-          "mimes": [
-            "video/mp4"
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-id",
-              "banner": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "format": [
-                  {
-                    "w": 300,
-                    "h": 250
-                  },
-                  {
-                    "w": 300,
-                    "h": 600
-                  }
-                ],
-                "w": 300,
-                "h": 250
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            },
-            {
-              "id": "unsupported-native-imp",
-              "native": {
-                "ver": "1.1",
-                "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}"
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            },
-            {
-              "id": "unsupported-audio-imp",
-              "audio": {
-                "mimes": [
-                  "video/mp4"
-                ]
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "seatbid": [
-            {
-              "seat": "958",
-              "bid": [{
-                "id": "7706636740145184841",
-                "impid": "test-imp-id",
-                "price": 0.500000,
-                "adid": "29681110",
-                "adm": "some-test-ad",
-                "adomain": ["yahoo.com"],
-                "cid": "958",
-                "crid": "29681110",
-                "h": 250,
-                "w": 300
-              }]
-            }
-          ],
-          "bidid": "5778926625248726496",
-          "cur": "USD"
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [
-        {
-          "bid": {
-            "id": "7706636740145184841",
-            "impid": "test-imp-id",
-            "price": 0.5,
-            "adm": "some-test-ad",
-            "adid": "29681110",
-            "adomain": ["yahoo.com"],
-            "cid": "958",
-            "crid": "29681110",
-            "w": 300,
-            "h": 250
-          },
-          "type": "banner"
-        }
-      ]
-    }
-  ]
-
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/banner-video-native.json b/adapters/brightroll/brightrolltest/exemplary/banner-video-native.json
deleted file mode 100644
index 97081b70..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/banner-video-native.json
+++ /dev/null
@@ -1,176 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      },
-      {
-        "id": "unsupported-native-imp",
-        "native": {
-          "ver": "1.1",
-          "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}"
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      },
-      {
-        "id": "test-imp-video-id",
-        "video": {
-          "mimes": ["video/mp4"],
-          "protocols": [2, 5],
-          "w": 1024,
-          "h": 576
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-id",
-              "banner": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "format": [
-                  {
-                    "w": 300,
-                    "h": 250
-                  },
-                  {
-                    "w": 300,
-                    "h": 600
-                  }
-                ],
-                "w": 300,
-                "h": 250
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            },
-            {
-              "id": "unsupported-native-imp",
-              "native": {
-                "ver": "1.1",
-                "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}"
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            },
-            {
-              "id": "test-imp-video-id",
-              "video": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "mimes": ["video/mp4"],
-                "protocols": [2, 5],
-                "w": 1024,
-                "h": 576
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "seatbid": [
-            {
-              "seat": "958",
-              "bid": [{
-                "id": "7706636740145184841",
-                "impid": "test-imp-video-id",
-                "price": 0.500000,
-                "adid": "29681110",
-                "adm": "some-test-ad",
-                "adomain": ["yahoo.com"],
-                "cid": "958",
-                "crid": "29681110",
-                "h": 576,
-                "w": 1024
-              }]
-            }
-          ],
-          "bidid": "5778926625248726496",
-          "cur": "USD"
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [
-        {
-          "bid": {
-            "id": "7706636740145184841",
-            "impid": "test-imp-video-id",
-            "price": 0.5,
-            "adm": "some-test-ad",
-            "adid": "29681110",
-            "adomain": ["yahoo.com"],
-            "cid": "958",
-            "crid": "29681110",
-            "w": 1024,
-            "h": 576
-          },
-          "type": "video"
-        }
-      ]
-    }
-  ]
-
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/banner-video.json b/adapters/brightroll/brightrolltest/exemplary/banner-video.json
deleted file mode 100644
index 17441152..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/banner-video.json
+++ /dev/null
@@ -1,152 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      },
-      {
-        "id": "test-imp-video-id",
-        "video": {
-          "mimes": ["video/mp4"],
-          "protocols": [2, 5],
-          "w": 1024,
-          "h": 576
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-id",
-              "banner": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "format": [
-                  {
-                    "w": 300,
-                    "h": 250
-                  },
-                  {
-                    "w": 300,
-                    "h": 600
-                  }
-                ],
-                "w": 300,
-                "h": 250
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            },
-            {
-              "id": "test-imp-video-id",
-              "video": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "mimes": ["video/mp4"],
-                "protocols": [2, 5],
-                "w": 1024,
-                "h": 576
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "seatbid": [
-            {
-              "seat": "958",
-              "bid": [{
-                "id": "7706636740145184841",
-                "impid": "test-imp-video-id",
-                "price": 0.500000,
-                "adid": "29681110",
-                "adm": "some-test-ad",
-                "adomain": ["yahoo.com"],
-                "cid": "958",
-                "crid": "29681110",
-                "h": 576,
-                "w": 1024
-              }]
-            }
-          ],
-          "bidid": "5778926625248726496",
-          "cur": "USD"
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [
-        {
-          "bid": {
-            "id": "7706636740145184841",
-            "impid": "test-imp-video-id",
-            "price": 0.5,
-            "adm": "some-test-ad",
-            "adid": "29681110",
-            "adomain": ["yahoo.com"],
-            "cid": "958",
-            "crid": "29681110",
-            "w": 1024,
-            "h": 576
-          },
-          "type": "video"
-        }
-      ]
-    }
-  ]
-
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/simple-banner.json b/adapters/brightroll/brightrolltest/exemplary/simple-banner.json
deleted file mode 100644
index f5903850..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/simple-banner.json
+++ /dev/null
@@ -1,119 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      }
-    ]
-  },
-
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-id",
-              "banner": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "format": [
-                  {
-                    "w": 300,
-                    "h": 250
-                  },
-                  {
-                    "w": 300,
-                    "h": 600
-                  }
-                ],
-                "w": 300,
-                "h": 250
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "seatbid": [
-            {
-              "seat": "958",
-              "bid": [{
-                "id": "7706636740145184841",
-                "impid": "test-imp-id",
-                "price": 0.500000,
-                "adid": "29681110",
-                "adm": "some-test-ad",
-                "adomain": ["yahoo.com"],
-                "cid": "958",
-                "crid": "29681110",
-                "h": 250,
-                "w": 300
-              }]
-            }
-          ],
-          "bidid": "5778926625248726496",
-          "cur": "USD"
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [
-        {
-          "bid": {
-            "id": "7706636740145184841",
-            "impid": "test-imp-id",
-            "price": 0.5,
-            "adm": "some-test-ad",
-            "adid": "29681110",
-            "adomain": ["yahoo.com"],
-            "cid": "958",
-            "crid": "29681110",
-            "w": 300,
-            "h": 250
-          },
-          "type": "banner"
-        }
-      ]
-    }
-  ]
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/simple-video.json b/adapters/brightroll/brightrolltest/exemplary/simple-video.json
deleted file mode 100644
index 88539276..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/simple-video.json
+++ /dev/null
@@ -1,98 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-id",
-        "video": {
-          "mimes": ["video/mp4"],
-          "protocols": [2, 5],
-          "w": 1024,
-          "h": 576
-        },
-        "ext":{
-          "bidder":{
-            "publisher": "adthrive"
-          }
-        }
-      }
-    ]
-  },
-
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-id",
-              "video": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "mimes": ["video/mp4"],
-                "protocols": [2, 5],
-                "w": 1024,
-                "h": 576
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "cur": "USD",
-          "seatbid": [
-            {
-              "seat": "Brightroll",
-              "bid": [{
-                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
-                "impid": "test-imp-id",
-                "price": 0.500000,
-                "adm": "some-test-ad",
-                "crid": "crid_10",
-                "w": 1024,
-                "h": 576
-              }]
-            }
-          ]
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [
-        {
-          "bid": {
-            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
-            "impid": "test-imp-id",
-            "price": 0.5,
-            "adm": "some-test-ad",
-            "crid": "crid_10",
-            "w": 1024,
-            "h": 576
-          },
-          "type": "video"
-        }
-      ]
-    }
-  ]
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/valid-extension.json b/adapters/brightroll/brightrolltest/exemplary/valid-extension.json
deleted file mode 100644
index 9a5e571c..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/valid-extension.json
+++ /dev/null
@@ -1,96 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-id",
-        "video": {
-          "mimes": ["video/mp4"],
-          "protocols": [2, 5],
-          "w": 1024,
-          "h": 576
-        },
-        "ext":{
-          "bidder":{
-            "publisher": "adthrive"
-           }
-        }
-      }
-    ]
-  },
-
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-id",
-              "video": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "mimes": ["video/mp4"],
-                "protocols": [2, 5],
-                "w": 1024,
-                "h": 576
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "cur": "USD",
-          "seatbid": [
-            {
-              "seat": "brightroll",
-              "bid": [{
-                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
-                "impid": "test-imp-id",
-                "price": 0.500000,
-                "adm": "some-test-ad",
-                "crid": "crid_10",
-                "w": 1024,
-                "h": 576
-              }]
-            }
-          ]
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [{
-        "bid": {
-          "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
-          "impid": "test-imp-id",
-          "price": 0.5,
-          "adm": "some-test-ad",
-          "crid": "crid_10",
-          "w": 1024,
-          "h": 576
-        },
-        "type": "video"
-      }]
-    }
-  ]
-}
diff --git a/adapters/brightroll/brightrolltest/exemplary/video-and-audio.json b/adapters/brightroll/brightrolltest/exemplary/video-and-audio.json
deleted file mode 100644
index 4184842b..00000000
--- a/adapters/brightroll/brightrolltest/exemplary/video-and-audio.json
+++ /dev/null
@@ -1,121 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-imp-video-id",
-        "video": {
-          "mimes": ["video/mp4"],
-          "protocols": [2, 5],
-          "w": 1024,
-          "h": 576
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      },
-      {
-        "id": "unsupported-audio-imp",
-        "audio": {
-          "mimes": [
-            "video/mp4"
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher": "adthrive"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "uri": "http://test-bid.ybp.yahoo.com/bid/appnexuspbs?publisher=adthrive",
-        "body": {
-          "id": "test-request-id",
-          "at":1,
-          "bcat": [
-            "IAB8-5",
-            "IAB8-18"
-          ],
-          "imp": [
-            {
-              "id": "test-imp-video-id",
-              "video": {
-                "battr": [
-                  1,
-                  2,
-                  3
-                ],
-                "mimes": ["video/mp4"],
-                "protocols": [2, 5],
-                "w": 1024,
-                "h": 576
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            },
-            {
-              "id": "unsupported-audio-imp",
-              "audio": {
-                "mimes": [
-                  "video/mp4"
-                ]
-              },
-              "ext": {
-                "bidder": {
-                  "publisher": "adthrive"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "test-request-id",
-          "cur": "USD",
-          "seatbid": [
-            {
-              "seat": "brightroll",
-              "bid": [{
-                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
-                "impid": "test-imp-video-id",
-                "price": 0.500000,
-                "adm": "some-test-ad",
-                "crid": "crid_10",
-                "w": 1024,
-                "h": 576
-              }]
-            }
-          ]
-        }
-      }
-    }
-  ],
-
-  "expectedBidResponses": [
-    {
-      "bids": [{
-        "bid": {
-          "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
-          "impid": "test-imp-video-id",
-          "price": 0.5,
-          "adm": "some-test-ad",
-          "crid": "crid_10",
-          "w": 1024,
-          "h": 576
-        },
-        "type": "video"
-      }]
-    }
-  ]
-}
diff --git a/adapters/brightroll/brightrolltest/supplemental/invalid-extension.json b/adapters/brightroll/brightrolltest/supplemental/invalid-extension.json
deleted file mode 100644
index 35b15638..00000000
--- a/adapters/brightroll/brightrolltest/supplemental/invalid-extension.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-invalid-ext-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-        }
-
-      }
-    ]
-  },
-  "expectedMakeRequestsErrors": [
-    {
-      "value": "ext.bidder.publisher not provided",
-      "comparison": "literal"
-    }
-  ]
-}
diff --git a/adapters/brightroll/brightrolltest/supplemental/invalid-imp.json b/adapters/brightroll/brightrolltest/supplemental/invalid-imp.json
deleted file mode 100644
index 01beec71..00000000
--- a/adapters/brightroll/brightrolltest/supplemental/invalid-imp.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "ext": {
-      "bidder": {
-        "publisher": "adthrive"
-      }
-    }
-  },
-  "expectedMakeRequestsErrors": [
-    {
-      "value": "No impression in the bid request",
-      "comparison": "literal"
-    }
-  ]
-}
diff --git a/adapters/brightroll/brightrolltest/supplemental/invalid-publisher.json b/adapters/brightroll/brightrolltest/supplemental/invalid-publisher.json
deleted file mode 100644
index da48108a..00000000
--- a/adapters/brightroll/brightrolltest/supplemental/invalid-publisher.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-missing-req-param-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher":"test"
-          }
-        }
-
-      }
-    ]
-  },
-  "expectedMakeRequestsErrors": [
-    {
-      "value": "Invalid publisher",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/brightroll/brightrolltest/supplemental/missing-extension.json b/adapters/brightroll/brightrolltest/supplemental/missing-extension.json
deleted file mode 100644
index 82ec775d..00000000
--- a/adapters/brightroll/brightrolltest/supplemental/missing-extension.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-missing-ext-id",
-        "video": {
-          "mimes": ["video/mp4"],
-          "protocols": [2, 5],
-          "w": 1024,
-          "h": 576
-        }
-      }
-    ]
-  },
-  "expectedMakeRequestsErrors": [
-    {
-      "value": "ext.bidder not provided",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/brightroll/brightrolltest/supplemental/missing-param.json b/adapters/brightroll/brightrolltest/supplemental/missing-param.json
deleted file mode 100644
index 08e82c0e..00000000
--- a/adapters/brightroll/brightrolltest/supplemental/missing-param.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-      {
-        "id": "test-missing-req-param-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 250
-            },
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "ext": {
-          "bidder": {
-            "publisher":""
-          }
-        }
-
-      }
-    ]
-  },
-  "expectedMakeRequestsErrors": [
-    {
-      "value": "publisher is empty",
-      "comparison": "literal"
-    }
-  ]
-}
diff --git a/adapters/brightroll/params_test.go b/adapters/brightroll/params_test.go
deleted file mode 100644
index c14ee6d7..00000000
--- a/adapters/brightroll/params_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package brightroll
-
-import (
-	"encoding/json"
-	"testing"
-
-	"github.com/prebid/prebid-server/openrtb_ext"
-)
-
-// This file actually intends to test static/bidder-params/brightroll.json
-//
-// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.brightroll
-
-// TestValidParams makes sure that the Brightroll schema accepts all imp.ext fields which we intend to support.
-func TestValidParams(t *testing.T) {
-	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
-	if err != nil {
-		t.Fatalf("Failed to fetch the json-schemas. %v", err)
-	}
-
-	for _, validParam := range validParams {
-		if err := validator.Validate(openrtb_ext.BidderBrightroll, json.RawMessage(validParam)); err != nil {
-			t.Errorf("Schema rejected Brightroll params: %s", validParam)
-		}
-	}
-}
-
-// TestInvalidParams makes sure that the Brightroll schema rejects all the imp.ext fields we don't support.
-func TestInvalidParams(t *testing.T) {
-	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
-	if err != nil {
-		t.Fatalf("Failed to fetch the json-schemas. %v", err)
-	}
-
-	for _, invalidParam := range invalidParams {
-		if err := validator.Validate(openrtb_ext.BidderBrightroll, json.RawMessage(invalidParam)); err == nil {
-			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
-		}
-	}
-}
-
-var validParams = []string{
-	`{"publisher": "testpublisher"}`,
-	`{"publisher": "123"}`,
-	`{"publisher": "cafemedia"}`,
-	`{"publisher": "test", "headerbidding": false}`,
-}
-
-var invalidParams = []string{
-	`{"publisher": 100}`,
-	`{"headerbidding": false}`,
-	`{"publisher": true}`,
-	`{"publisherId": 123, "headerbidding": true}`,
-	`{"publisherID": "1"}`,
-	``,
-	`null`,
-	`true`,
-	`9`,
-	`1.2`,
-	`[]`,
-	`{}`,
-}
diff --git a/adapters/gamma/params_test.go b/adapters/gamma/params_test.go
index 56f1b591..c6a149c2 100644
--- a/adapters/gamma/params_test.go
+++ b/adapters/gamma/params_test.go
@@ -8,8 +8,6 @@ import (
 )
 
 // This file actually intends to test static/bidder-params/gamma.json
-//
-// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.brightroll
 
 // TestValidParams makes sure that the Gamma schema accepts all imp.ext fields which we intend to support.
 func TestValidParams(t *testing.T) {
diff --git a/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps-multi-format.json b/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps-multi-format.json
new file mode 100644
index 00000000..c31cb1ce
--- /dev/null
+++ b/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps-multi-format.json
@@ -0,0 +1,154 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 320,
+                            "h": 50
+                        }
+                    ]
+                },
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "protocols": [
+                        2,
+                        5
+                    ],
+                    "w": 320,
+                    "h": 480
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 123456,
+                        "pub_id": 1234
+                    }
+                }
+            },
+            {
+                "id": "2",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 50
+                        }
+                    ]
+                },
+                "native": {
+                    "ver": "1.2",
+                    "request": "{\"native\":{\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"url\":\"...\"}},{\"id\":1,\"required\":1,\"title\":{\"text\":\"custom title\"}}]}}"
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 234567,
+                        "pub_id": 1234
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://mfx.mobilefuse.com/openrtb?pub_id=1234",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 320,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "protocols": [
+                                    2,
+                                    5
+                                ],
+                                "w": 320,
+                                "h": 480
+                            },
+                            "tagid": "123456"
+                        },
+                        {
+                            "id": "2",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "native": {
+                                "ver": "1.2",
+                                "request": "{\"native\":{\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"url\":\"...\"}},{\"id\":1,\"required\":1,\"title\":{\"text\":\"custom title\"}}]}}"
+                            },
+                            "tagid": "234567"
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "mobilefuse",
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "1",
+                                    "price": 1.50,
+                                    "adm": "some-test-ad",
+                                    "crid": "test-crid",
+                                    "h": 50,
+                                    "w": 320,
+                                    "ext": {
+                                        "mf": {
+                                            "media_type": "banner"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "1",
+                        "price": 1.50,
+                        "adm": "some-test-ad",
+                        "crid": "test-crid",
+                        "w": 320,
+                        "h": 50
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps.json b/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps.json
index 568e51af..15ba4f96 100644
--- a/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps.json
+++ b/adapters/mobilefuse/mobilefusetest/exemplary/multi-imps.json
@@ -57,6 +57,18 @@
                                 ]
                             },
                             "tagid": "123456"
+                        },
+                        {
+                            "id": "2",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "tagid": "234567"
                         }
                     ]
                 }
diff --git a/adapters/orbidder/orbiddertest/exemplary/multibid-multi-format-with-mtype.json b/adapters/orbidder/orbiddertest/exemplary/multibid-multi-format-with-mtype.json
new file mode 100644
index 00000000..011acb2c
--- /dev/null
+++ b/adapters/orbidder/orbiddertest/exemplary/multibid-multi-format-with-mtype.json
@@ -0,0 +1,185 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "site": {
+      "page": "https://test.orbidder.de"
+    },
+    "user": {
+      "buyeruid": "XX672XXX-5XXd-4XX2-8XX6-6XXXXc9cXXXX.v1"
+    },
+    "imp": [
+      {
+        "id": "multi-format-test-imp-id-1",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "native": {
+          "ver":"1.2",
+          "request":"\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":140},{\"id\":1,\"img\":{\"h\":250,\"hmin\":0,\"type\":3,\"w\":300,\"wmin\":0}}]"
+        },
+        "ext": {
+          "bidder": {
+            "accountId": "orbidder-test",
+            "placementId": "web-test-placement-1",
+            "bidfloor": 0.1
+          }
+        }
+      },{
+        "id": "multi-format-test-imp-id-2",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "native": {
+          "ver":"1.2",
+          "request":"\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":140},{\"id\":1,\"img\":{\"h\":250,\"hmin\":0,\"type\":3,\"w\":300,\"wmin\":0}}]"
+        },
+        "ext": {
+          "bidder": {
+            "accountId": "orbidder-test",
+            "placementId": "web-test-placement-2",
+            "bidfloor": 0.1
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://orbidder-test",
+        "body": {
+          "id": "test-request-id",
+          "site": {
+            "page": "https://test.orbidder.de"
+          },
+          "user": {
+            "buyeruid": "XX672XXX-5XXd-4XX2-8XX6-6XXXXc9cXXXX.v1"
+          },
+          "imp": [
+            {
+              "id": "multi-format-test-imp-id-1",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "native": {
+                "ver":"1.2",
+                "request":"\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":140},{\"id\":1,\"img\":{\"h\":250,\"hmin\":0,\"type\":3,\"w\":300,\"wmin\":0}}]"
+              },
+              "bidfloorcur": "EUR",
+              "ext": {
+                "bidder": {
+                  "accountId": "orbidder-test",
+                  "placementId": "web-test-placement-1",
+                  "bidfloor": 0.1
+                }
+              }
+            },{
+              "id": "multi-format-test-imp-id-2",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "native": {
+                "ver":"1.2",
+                "request":"\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":140},{\"id\":1,\"img\":{\"h\":250,\"hmin\":0,\"type\":3,\"w\":300,\"wmin\":0}}]"
+              },
+              "bidfloorcur": "EUR",
+              "ext": {
+                "bidder": {
+                  "accountId": "orbidder-test",
+                  "placementId": "web-test-placement-2",
+                  "bidfloor": 0.1
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "seat-id",
+              "bid": [
+                {
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e900",
+                  "impid": "multi-format-test-imp-id-1",
+                  "adid": "11110126",
+                  "price": 0.600000,
+                  "adm": "banner-some-test-ad",
+                  "crid": "banner-test-crid",
+                  "h": 250,
+                  "w": 300,
+                  "mtype": 1
+                },{
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "multi-format-test-imp-id-2",
+                  "adid": "11110136",
+                  "price": 0.500000,
+                  "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"text\":\"Orbidder rocks\"}},{\"id\":1,\"required\":1,\"img\":{\"url\":\"https://prd.orbidder.de/common/logo.png\"}}],\"link\":{\"url\":\"https://www.otto.de/\",\"clicktrackers\":[\"https://prd.orbidder.de/click\"]},\"imptrackers\":[\"https://prd.orbidder.de/imp\"]}",
+                  "crid": "native-test-crid",
+                  "mtype": 4
+                }
+              ]
+            }
+          ],
+          "bidid": "5778926625248726496",
+          "cur": "EUR"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e900",
+            "impid": "multi-format-test-imp-id-1",
+            "adid": "11110126",
+            "price": 0.6,
+            "adm": "banner-some-test-ad",
+            "crid": "banner-test-crid",
+            "w": 300,
+            "h": 250,
+            "mtype": 1
+          },
+          "type": "banner"
+        },{
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "multi-format-test-imp-id-2",
+            "adid": "11110136",
+            "price": 0.5,
+            "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"text\":\"Orbidder rocks\"}},{\"id\":1,\"required\":1,\"img\":{\"url\":\"https://prd.orbidder.de/common/logo.png\"}}],\"link\":{\"url\":\"https://www.otto.de/\",\"clicktrackers\":[\"https://prd.orbidder.de/click\"]},\"imptrackers\":[\"https://prd.orbidder.de/imp\"]}",
+            "crid": "native-test-crid",
+            "mtype": 4
+          },
+          "type": "native"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json b/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json
index 2315a52c..80b3c794 100644
--- a/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json
+++ b/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json
@@ -79,7 +79,8 @@
                   "adm": "some-test-ad",
                   "crid": "test-crid",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "mtype": 1
                 }
               ]
             }
@@ -102,7 +103,8 @@
             "adm": "some-test-ad",
             "crid": "test-crid",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "mtype": 1
           },
           "type": "banner"
         }
diff --git a/adapters/orbidder/orbiddertest/exemplary/simple-web-banner.json b/adapters/orbidder/orbiddertest/exemplary/simple-web-banner.json
new file mode 100644
index 00000000..9e1181a5
--- /dev/null
+++ b/adapters/orbidder/orbiddertest/exemplary/simple-web-banner.json
@@ -0,0 +1,114 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "site": {
+      "page": "https://test.orbidder.de"
+    },
+    "user": {
+      "buyeruid": "XX672XXX-5XXd-4XX2-8XX6-6XXXXc9cXXXX.v1"
+    },
+    "imp": [
+      {
+        "id": "web-test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "accountId": "orbidder-test",
+            "placementId": "web-test-placement",
+            "bidfloor": 0.1
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://orbidder-test",
+        "body": {
+          "id": "test-request-id",
+          "site": {
+            "page": "https://test.orbidder.de"
+          },
+          "user": {
+            "buyeruid": "XX672XXX-5XXd-4XX2-8XX6-6XXXXc9cXXXX.v1"
+          },
+          "imp": [
+            {
+              "id": "web-test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "bidfloorcur": "EUR",
+              "ext": {
+                "bidder": {
+                  "accountId": "orbidder-test",
+                  "placementId": "web-test-placement",
+                  "bidfloor": 0.1
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "web-test-request-id",
+          "seatbid": [
+            {
+              "seat": "web-seat-id",
+              "bid": [
+                {
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "web-test-imp-id",
+                  "adid": "11110126",
+                  "price": 0.600000,
+                  "adm": "web-some-test-ad",
+                  "crid": "web-test-crid",
+                  "h": 250,
+                  "w": 300,
+                  "mtype": 1
+                }
+              ]
+            }
+          ],
+          "cur": "EUR"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "EUR",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "web-test-imp-id",
+            "adid": "11110126",
+            "price": 0.6,
+            "adm": "web-some-test-ad",
+            "crid": "web-test-crid",
+            "w": 300,
+            "h": 250,
+            "mtype": 1
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/orbidder/orbiddertest/exemplary/simple-web-native.json b/adapters/orbidder/orbiddertest/exemplary/simple-web-native.json
new file mode 100644
index 00000000..f4b8ec2c
--- /dev/null
+++ b/adapters/orbidder/orbiddertest/exemplary/simple-web-native.json
@@ -0,0 +1,102 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "site": {
+      "page": "test.orbidder.de"
+    },
+    "user": {
+      "buyeruid": "test-user"
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "native": {
+          "ver":"1.2",
+          "request":"\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":140},{\"id\":1,\"img\":{\"h\":250,\"hmin\":0,\"type\":3,\"w\":300,\"wmin\":0}}]"
+        },
+        "ext": {
+          "bidder": {
+            "accountId": "orbidder-test",
+            "placementId": "test-placement",
+            "bidfloor": 0.1
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://orbidder-test",
+        "body": {
+          "id": "test-request-id",
+          "site": {
+            "page": "test.orbidder.de"
+          },
+          "user": {
+            "buyeruid": "test-user"
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "native": {
+                "ver":"1.2",
+                "request":"\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":140},{\"id\":1,\"img\":{\"h\":250,\"hmin\":0,\"type\":3,\"w\":300,\"wmin\":0}}]"
+              },
+              "bidfloorcur": "EUR",
+              "ext": {
+                "bidder": {
+                  "accountId": "orbidder-test",
+                  "placementId": "test-placement",
+                  "bidfloor": 0.1
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "seat-id",
+              "bid": [
+                {
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "test-imp-id",
+                  "adid": "11110126",
+                  "price": 0.500000,
+                  "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"text\":\"Orbidder rocks\"}},{\"id\":1,\"required\":1,\"img\":{\"url\":\"https://prd.orbidder.de/common/logo.png\"}}],\"link\":{\"url\":\"https://www.otto.de/\",\"clicktrackers\":[\"https://prd.orbidder.de/click\"]},\"imptrackers\":[\"https://prd.orbidder.de/imp\"]}",
+                  "crid": "test-crid",
+                  "mtype": 4
+                }
+              ]
+            }
+          ],
+          "cur": "EUR"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "EUR",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "adid": "11110126",
+            "price": 0.5,
+            "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"text\":\"Orbidder rocks\"}},{\"id\":1,\"required\":1,\"img\":{\"url\":\"https://prd.orbidder.de/common/logo.png\"}}],\"link\":{\"url\":\"https://www.otto.de/\",\"clicktrackers\":[\"https://prd.orbidder.de/click\"]},\"imptrackers\":[\"https://prd.orbidder.de/imp\"]}",
+            "crid": "test-crid",
+            "mtype": 4
+          },
+          "type": "native"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json b/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json
index 1ea133ab..5b4a523f 100644
--- a/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json
+++ b/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json
@@ -85,7 +85,8 @@
                   "adm": "some-test-ad",
                   "crid": "test-crid",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "mtype": 1
                 }
               ]
             }
@@ -108,7 +109,8 @@
             "adm": "some-test-ad",
             "crid": "test-crid",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "mtype": 1
           },
           "type": "banner"
         }
diff --git a/adapters/ownadx/ownadx_test.go b/adapters/ownadx/ownadx_test.go
new file mode 100644
index 00000000..9bd7ba70
--- /dev/null
+++ b/adapters/ownadx/ownadx_test.go
@@ -0,0 +1,17 @@
+package ownadx
+
+import (
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderOwnAdx, config.Adapter{
+		Endpoint: "https://pbs.prebid-ownadx.com/bidder/bid/{{.AccountID}}/{{.ZoneID}}?token={{.SourceId}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	assert.NoError(t, buildErr)
+	adapterstest.RunJSONBidderTest(t, "ownadxtest", bidder)
+}
diff --git a/adapters/ownadx/ownadxtest/exemplary/banner.json b/adapters/ownadx/ownadxtest/exemplary/banner.json
new file mode 100644
index 00000000..f77321c5
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/exemplary/banner.json
@@ -0,0 +1,166 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "mtype": 1,
+                  "id": "id",
+                  "impid": "id",
+                  "price": 0.1,
+                  "nurl": "http://test.com/nurl",
+                  "burl": "http://test.com/burl",
+                  "adm": "<span>Test</span>",
+                  "adomain": [
+                    "test.com"
+                  ],
+                  "cat": [
+                    "IAB1"
+                  ],
+                  "cid": "cid",
+                  "crid": "crid",
+                  "w": 300,
+                  "h": 250,
+                  "ext": {
+                    "mediaType": "banner"
+                  }
+                }
+              ],
+              "seat": "seat"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "mtype": 1,
+            "id": "id",
+            "impid": "id",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "<span>Test</span>",
+            "adomain": [
+              "test.com"
+            ],
+            "cat": [
+              "IAB1"
+            ],
+            "cid": "cid",
+            "crid": "crid",
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "mediaType": "banner"
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/exemplary/video.json b/adapters/ownadx/ownadxtest/exemplary/video.json
new file mode 100644
index 00000000..7cac425c
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/exemplary/video.json
@@ -0,0 +1,196 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "video": {
+          "mimes": [
+            "video/mp4",
+            "video/ogg",
+            "video/webm"
+          ],
+          "minduration": 3,
+          "maxduration": 3000,
+          "protocols": [
+            2,
+            3,
+            5,
+            6,
+            7,
+            8
+          ],
+          "w": 480,
+          "h": 320,
+          "linearity": 1,
+          "playbackmethod": [
+            2
+          ],
+          "pos": 0
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "video": {
+                "mimes": [
+                  "video/mp4",
+                  "video/ogg",
+                  "video/webm"
+                ],
+                "minduration": 3,
+                "maxduration": 3000,
+                "protocols": [
+                  2,
+                  3,
+                  5,
+                  6,
+                  7,
+                  8
+                ],
+                "w": 480,
+                "h": 320,
+                "linearity": 1,
+                "playbackmethod": [
+                  2
+                ],
+                "pos": 0
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "id",
+                  "impid": "id",
+                  "price": 0.1,
+                  "nurl": "http://test.com/nurl",
+                  "burl": "http://test.com/burl",
+                  "adm": "<VAST>",
+                  "adomain": [
+                    "test.com"
+                  ],
+                  "cat": [
+                    "IAB1"
+                  ],
+                  "cid": "cid",
+                  "crid": "crid",
+                  "mtype": 2
+                }
+              ],
+              "seat": "seat"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "id",
+            "impid": "id",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "<VAST>",
+            "adomain": [
+              "test.com"
+            ],
+            "cat": [
+              "IAB1"
+            ],
+            "cid": "cid",
+            "crid": "crid",
+            "mtype": 2
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/bad-server-response.json b/adapters/ownadx/ownadxtest/supplemental/bad-server-response.json
new file mode 100644
index 00000000..61b6da04
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/bad-server-response.json
@@ -0,0 +1,108 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200
+
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad server response ",
+      "comparison": "literal"
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/bid-empty-.json b/adapters/ownadx/ownadxtest/supplemental/bid-empty-.json
new file mode 100644
index 00000000..8d40e878
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/bid-empty-.json
@@ -0,0 +1,118 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "seatbid": [
+            {
+              "seat": "seat"
+            }
+          ],
+          "cur": "USD"
+        }
+
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bid cannot be empty ",
+      "comparison": "literal"
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/bidext-type.json b/adapters/ownadx/ownadxtest/supplemental/bidext-type.json
new file mode 100644
index 00000000..b1d63428
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/bidext-type.json
@@ -0,0 +1,141 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "id",
+                  "impid": "id",
+                  "price": 0.1,
+                  "nurl": "http://test.com/nurl",
+                  "burl": "http://test.com/burl",
+                  "adm": "<span>Test</span>",
+                  "adomain": [
+                    "test.com"
+                  ],
+                  "cat": [
+                    "IAB1"
+                  ],
+                  "cid": "cid",
+                  "crid": "crid",
+                  "w": 300,
+                  "h": 250,
+                  "ext": {
+
+                  }
+                }
+              ],
+              "seat": "seat"
+            }
+          ],
+          "cur": "USD"
+        }
+
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bid type is invalid",
+      "comparison": "literal"
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/http-status-204.json b/adapters/ownadx/ownadxtest/supplemental/http-status-204.json
new file mode 100644
index 00000000..4b7f8663
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/http-status-204.json
@@ -0,0 +1,51 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 204
+      }
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/http-status-400.json b/adapters/ownadx/ownadxtest/supplemental/http-status-400.json
new file mode 100644
index 00000000..035bc323
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/http-status-400.json
@@ -0,0 +1,57 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 400
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad request: 400",
+      "comparison": "literal"
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/invalid-req-empty-imp.json b/adapters/ownadx/ownadxtest/supplemental/invalid-req-empty-imp.json
new file mode 100644
index 00000000..0407ed6c
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/invalid-req-empty-imp.json
@@ -0,0 +1,34 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "No impression in the bid request",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "id",
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/ownadx/ownadxtest/supplemental/invalid-req-imp-ext.json b/adapters/ownadx/ownadxtest/supplemental/invalid-req-imp-ext.json
new file mode 100644
index 00000000..9b8ba0d1
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/invalid-req-imp-ext.json
@@ -0,0 +1,47 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Bidder extension not valid or can't be unmarshalled",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        }
+
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/ownadx/ownadxtest/supplemental/invalid-req-imp.ext.bidder.json b/adapters/ownadx/ownadxtest/supplemental/invalid-req-imp.ext.bidder.json
new file mode 100644
index 00000000..b04e037d
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/invalid-req-imp.ext.bidder.json
@@ -0,0 +1,49 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Error while unmarshaling bidder extension",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": []
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/ownadx/ownadxtest/supplemental/seatbid-empty-.json b/adapters/ownadx/ownadxtest/supplemental/seatbid-empty-.json
new file mode 100644
index 00000000..f49ece3e
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/seatbid-empty-.json
@@ -0,0 +1,113 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "cur": "USD"
+        }
+
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Array SeatBid cannot be empty ",
+      "comparison": "literal"
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/ownadx/ownadxtest/supplemental/unexpected-status.json b/adapters/ownadx/ownadxtest/supplemental/unexpected-status.json
new file mode 100644
index 00000000..f501a110
--- /dev/null
+++ b/adapters/ownadx/ownadxtest/supplemental/unexpected-status.json
@@ -0,0 +1,107 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [
+      {
+        "id": "id",
+        "secure": 1,
+        "bidfloor": 0.01,
+        "bidfloorcur": "USD",
+        "banner": {
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "tokenId": "126151698247",
+            "sspId": "11",
+            "seatId": "2"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": [
+        "IAB12"
+      ],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://pbs.prebid-ownadx.com/bidder/bid/2/11?token=126151698247",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "banner": {
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "tokenId": "126151698247",
+                  "sspId": "11",
+                  "seatId": "2"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 403
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 403. Run with request.test = 1 for more info.",
+      "comparison": "literal"
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/currency-conversion.json b/adapters/rtbhouse/rtbhousetest/exemplary/currency-conversion.json
new file mode 100644
index 00000000..95bfb1e4
--- /dev/null
+++ b/adapters/rtbhouse/rtbhousetest/exemplary/currency-conversion.json
@@ -0,0 +1,123 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "bidfloor": 1.00,
+          "bidfloorcur": "EUR",
+          "ext": {
+            "bidder": {
+              "placementId": "12345"
+            }
+          }
+        }
+      ],
+      "ext": {
+        "prebid": {
+          "currency": {
+            "rates": {
+              "EUR": {
+                "USD": 0.05
+              }
+            },
+            "usepbsrates": false
+          }
+        }
+      }
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://localhost/prebid_server",
+          "body": {
+            "id": "test-request-id",
+            "cur": ["USD"],
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "bidfloor": 0.05,
+                "bidfloorcur": "USD",
+                "ext": {
+                  "bidder": {
+                    "placementId": "12345"
+                  }
+                },
+                "id": "test-imp-id"
+              }
+            ],
+            "ext": {
+              "prebid": {
+                "currency": {
+                  "rates": {
+                    "EUR": {
+                      "USD": 0.05
+                    }
+                  },
+                  "usepbsrates": false
+                }
+              }
+             }
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "test-response-id",
+            "cur": "USD",
+            "seatbid": [{
+              "seat": "rtbhouse",
+              "bid": [{
+                "id": "randomid",
+                "impid": "test-imp-id",
+                "price": 300,
+                "adid": "12345678",
+                "adm": "some-test-ad",
+                "cid": "987",
+                "crid": "12345678",
+                "h": 250,
+                "w": 300
+                }
+              ]
+            }]
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [
+      {
+        "currency": "USD",
+        "bids": [
+          {
+            "bid": {
+              "id": "randomid",
+              "impid": "test-imp-id",
+              "price": 300,
+              "adid": "12345678",
+              "adm": "some-test-ad",
+              "cid": "987",
+              "crid": "12345678",
+              "h": 250,
+              "w": 300
+            },
+            "type": "banner"
+          }
+        ]
+      }
+    ]
+  }
diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/simple-banner.json b/adapters/rtbhouse/rtbhousetest/exemplary/simple-banner.json
index 3a636450..2a8c4681 100644
--- a/adapters/rtbhouse/rtbhousetest/exemplary/simple-banner.json
+++ b/adapters/rtbhouse/rtbhousetest/exemplary/simple-banner.json
@@ -23,6 +23,7 @@
             "uri": "http://localhost/prebid_server",
             "body": {
                 "id": "test-request-id",
+                "cur": ["USD"],
                 "site": {
                     "page": "https://good.site/url"
                 },
diff --git a/adapters/rtbhouse/rtbhousetest/supplemental/bad_response.json b/adapters/rtbhouse/rtbhousetest/supplemental/bad_response.json
index f84f5555..e0861fb0 100644
--- a/adapters/rtbhouse/rtbhousetest/supplemental/bad_response.json
+++ b/adapters/rtbhouse/rtbhousetest/supplemental/bad_response.json
@@ -26,6 +26,7 @@
         "uri": "http://localhost/prebid_server",
         "body": {
           "id": "test-request-id",
+          "cur": ["USD"],
           "imp": [
             {
               "id": "test-imp-id",
diff --git a/adapters/rtbhouse/rtbhousetest/supplemental/currency-missing-conversion.json b/adapters/rtbhouse/rtbhousetest/supplemental/currency-missing-conversion.json
new file mode 100644
index 00000000..d7d65e43
--- /dev/null
+++ b/adapters/rtbhouse/rtbhousetest/supplemental/currency-missing-conversion.json
@@ -0,0 +1,43 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "bidfloor": 1.00,
+          "bidfloorcur": "JPY",
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        }
+      ],
+      "ext": {
+        "prebid": {
+          "currency": {
+              "rates": {
+              "MXN": {
+                  "USD": 0.05
+              }
+              },
+              "usepbsrates": false
+          }
+        }
+      }
+    },
+    "expectedMakeRequestsErrors": [
+      {
+        "value": "Currency conversion rate not found: 'JPY' => 'USD'",
+        "comparison": "literal"
+      }
+    ]
+  }
diff --git a/adapters/rtbhouse/rtbhousetest/supplemental/status_204.json b/adapters/rtbhouse/rtbhousetest/supplemental/status_204.json
index 0702c103..bb7754ec 100644
--- a/adapters/rtbhouse/rtbhousetest/supplemental/status_204.json
+++ b/adapters/rtbhouse/rtbhousetest/supplemental/status_204.json
@@ -26,6 +26,7 @@
         "uri": "http://localhost/prebid_server",
         "body": {
           "id": "test-request-id",
+          "cur": ["USD"],
           "imp": [
             {
               "id": "test-imp-id",
diff --git a/adapters/rtbhouse/rtbhousetest/supplemental/status_400.json b/adapters/rtbhouse/rtbhousetest/supplemental/status_400.json
index 65d21406..0b527932 100644
--- a/adapters/rtbhouse/rtbhousetest/supplemental/status_400.json
+++ b/adapters/rtbhouse/rtbhousetest/supplemental/status_400.json
@@ -26,6 +26,7 @@
         "uri": "http://localhost/prebid_server",
         "body": {
           "id": "test-request-id",
+          "cur": ["USD"],
           "imp": [
             {
               "id": "test-imp-id",
diff --git a/adapters/rtbhouse/rtbhousetest/supplemental/status_418.json b/adapters/rtbhouse/rtbhousetest/supplemental/status_418.json
index 4c5dd576..6ff3860e 100644
--- a/adapters/rtbhouse/rtbhousetest/supplemental/status_418.json
+++ b/adapters/rtbhouse/rtbhousetest/supplemental/status_418.json
@@ -26,6 +26,7 @@
         "uri": "http://localhost/prebid_server",
         "body": {
           "id": "test-request-id",
+          "cur": ["USD"],
           "imp": [
             {
               "id": "test-imp-id",
diff --git a/adapters/vox/params_test.go b/adapters/vox/params_test.go
new file mode 100644
index 00000000..be148d3b
--- /dev/null
+++ b/adapters/vox/params_test.go
@@ -0,0 +1,56 @@
+package vox
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json schema. %v", err)
+	}
+
+	for _, p := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderVox, json.RawMessage(p)); err != nil {
+			t.Errorf("Schema rejected valid params: %s", p)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json schema. %v", err)
+	}
+
+	for _, p := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderVox, json.RawMessage(p)); err == nil {
+			t.Errorf("Schema allowed invalid params: %s", p)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"placementId": "64be6fe6685a271d37e900d2"}`,
+	`{"placementId": "Any String Basically"}`,
+	`{"placementId":""}`,
+	`{"placementId":"id", "imageUrl":"http://site.com/img1.png"}`,
+	`{"placementId":"id", "imageUrl":"http://site.com/img1.png", "displaySizes":["123x90", "1x1", "987x1111"]}`,
+}
+
+var invalidParams = []string{
+	`{"placementId": 42}`,
+	`{"placementId": null}`,
+	`{"placementId": 3.1415}`,
+	`{"placementId": true}`,
+	`{"placementId": false}`,
+	`{"placementId":"id", "imageUrl": null}`,
+	`{"placementId":"id", "imageUrl": true}`,
+	`{"placementId":"id", "imageUrl": []}`,
+	`{"placementId":"id", "imageUrl": "http://some.url", "displaySizes": null}`,
+	`{"placementId":"id", "imageUrl": "http://some.url", "displaySizes": {}}`,
+	`{"placementId":"id", "imageUrl": "http://some.url", "displaySizes": "String"}`,
+}
diff --git a/adapters/vox/vox_test.go b/adapters/vox/vox_test.go
new file mode 100644
index 00000000..95d11a8a
--- /dev/null
+++ b/adapters/vox/vox_test.go
@@ -0,0 +1,21 @@
+package vox
+
+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.BidderVox, config.Adapter{
+		Endpoint: "http://somecoolurlfor.vox"},
+		config.Server{ExternalUrl: "http://somecoolurlfor.vox", GvlID: 1, DataCenter: "2"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error: %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "voxtest", bidder)
+}
diff --git a/adapters/vox/voxtest/exemplary/banner.json b/adapters/vox/voxtest/exemplary/banner.json
new file mode 100644
index 00000000..898fcea4
--- /dev/null
+++ b/adapters/vox/voxtest/exemplary/banner.json
@@ -0,0 +1,82 @@
+{
+  "mockBidRequest": {
+    "id": "cf4b0abb-7ccc-4057-9914-c85f467260c6",
+    "site": {
+      "page": "http://some.site/url/page?id=338"
+    },
+    "cur": [ "USD" ],
+    "imp": [{
+        "id": "8a7510f9-0ca1-44c4-a8c6-1ce639b5eef9",
+        "banner": { "w": 100, "h": 100 },
+        "bidfloorcur": "USD",
+        "ext": {
+          "bidder": {
+            "placementId":"64b939146d66df22ccae95c5"
+          }
+        }
+      }]
+  },
+
+  "httpCalls": [{
+      "expectedRequest": {
+        "uri": "http://somecoolurlfor.vox",
+        "headers": {},
+        "body": {
+          "id": "cf4b0abb-7ccc-4057-9914-c85f467260c6",
+          "site": {
+            "page": "http://some.site/url/page?id=338"
+          },
+          "imp": [
+            {
+              "id": "8a7510f9-0ca1-44c4-a8c6-1ce639b5eef9",
+              "banner": {
+                "w": 100,
+                "h": 100
+              },
+              "bidfloorcur": "USD",
+              "ext": {
+                "bidder": {
+                  "placementId": "64b939146d66df22ccae95c5"
+                }
+              }
+            }
+          ],
+          "cur": [ "USD" ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "headers": {},
+        "body": {
+          "id": "cf4b0abb-7ccc-4057-9914-c85f467260c6",
+          "cur": "USD",
+          "seatbid": [{
+            "bid": [{
+              "id": "e6a143f3-5176-4607-b09e-0e67e358b0b6",
+              "impid": "8a7510f9-0ca1-44c4-a8c6-1ce639b5eef9",
+              "price": 3.1415,
+              "adm": "<html><h1>Hi, there</h1></html>",
+              "w": 50,
+              "h": 50,
+              "mtype": 1
+            }]
+           }]
+        }}
+    }],
+
+    "expectedBidResponses": [{
+      "bids": [{
+        "currency": "USD",
+        "bid": {
+          "id": "e6a143f3-5176-4607-b09e-0e67e358b0b6",
+          "impid": "8a7510f9-0ca1-44c4-a8c6-1ce639b5eef9",
+          "price": 3.1415,
+          "adm": "<html><h1>Hi, there</h1></html>",
+          "w": 50,
+          "h": 50,
+          "mtype": 1
+        },
+        "type": "banner"
+      }]
+    }]
+}
\ No newline at end of file
diff --git a/adapters/vox/voxtest/exemplary/video.json b/adapters/vox/voxtest/exemplary/video.json
new file mode 100644
index 00000000..37464da1
--- /dev/null
+++ b/adapters/vox/voxtest/exemplary/video.json
@@ -0,0 +1,87 @@
+{
+  "mockBidRequest": {
+    "id": "9a4bdb67-43ef-488f-937d-cd01e9dce43d",
+    "site": {
+      "page": "http://blog.com/article/1"
+    },
+    "cur": ["PLN"],
+    "imp": [{
+        "id": "d190d6f3-5264-4df5-91b2-8a9c72cbeb6a",
+        "bidfloorcur": "PLN",
+        "video": {
+          "mimes": ["video/mp4"],
+          "minduration": 5,
+          "maxduration": 15,
+          "w": 1280,
+          "h": 720
+        },
+        "ext": {
+          "bidder": {
+            "placementId":"64b9486efecad2330718e233"
+          }
+        }
+      }]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://somecoolurlfor.vox",
+      "header": {},
+      "body": {
+        "id": "9a4bdb67-43ef-488f-937d-cd01e9dce43d",
+        "site": {
+          "page": "http://blog.com/article/1"
+        },
+        "cur": [ "PLN" ],
+        "imp": [{
+            "id": "d190d6f3-5264-4df5-91b2-8a9c72cbeb6a",
+            "bidfloorcur": "PLN",
+            "video": {
+              "mimes": ["video/mp4"],
+              "minduration": 5,
+              "maxduration": 15,
+              "w": 1280,
+              "h": 720
+            },
+            "ext": {
+              "bidder": {
+                "placementId":"64b9486efecad2330718e233"
+              }
+            }
+          }]
+      }
+    },
+
+    "mockResponse": {
+      "status": 200,
+      "headers": {},
+      "body": {
+        "id":"d64fdeae-cb1c-4322-8fb6-18f5ec49bb76",
+        "cur": "PLN",
+        "seatbid": [{
+          "bid": [{
+            "id": "05349123-29e2-4be0-b662-48914f75ebe1",
+            "impid": "d190d6f3-5264-4df5-91b2-8a9c72cbeb6a",
+            "price": 2.149,
+            "adm": "<VAST>...</VAST>",
+            "mtype": 2
+          }]
+        }]
+      }
+    }
+  }],
+
+  "expectedBidResponses": [{
+    "bids": [{
+      "currency": "PLN",
+      "bid": {
+        "id": "05349123-29e2-4be0-b662-48914f75ebe1",
+        "impid": "d190d6f3-5264-4df5-91b2-8a9c72cbeb6a",
+        "price": 2.149,
+        "adm": "<VAST>...</VAST>",
+        "mtype": 2
+      },
+      "type": "video"
+    }]
+  }]
+}
\ No newline at end of file
diff --git a/adapters/vox/voxtest/supplemental/response_204_to_nocontent.json b/adapters/vox/voxtest/supplemental/response_204_to_nocontent.json
new file mode 100644
index 00000000..0a49b85d
--- /dev/null
+++ b/adapters/vox/voxtest/supplemental/response_204_to_nocontent.json
@@ -0,0 +1,45 @@
+{
+  "mockBidRequest": {
+    "id": "Some Id (445455)",
+    "cur": ["AUD"],
+    "imp": [{
+      "id": "Impression id #1",
+      "banner": {},
+      "bidfloorcur": "AUD",
+      "ext": {
+        "bidder": {
+          "placementId": "64b94ad4ed136806629dd51c"
+        }
+      }
+    }]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://somecoolurlfor.vox",
+      "headers": {},
+      "body": {
+        "id": "Some Id (445455)",
+        "cur": ["AUD"],
+        "imp": [{
+          "id": "Impression id #1",
+          "banner": {},
+          "bidfloorcur": "AUD",
+          "ext": {
+            "bidder": {
+              "placementId": "64b94ad4ed136806629dd51c"
+            }
+          }
+        }]
+      }
+    },
+
+    "mockResponse": {
+      "status": 204,
+      "headers": {},
+      "body": {}
+    }
+  }],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/vox/voxtest/supplemental/response_500_to_error.json b/adapters/vox/voxtest/supplemental/response_500_to_error.json
new file mode 100644
index 00000000..f245ef45
--- /dev/null
+++ b/adapters/vox/voxtest/supplemental/response_500_to_error.json
@@ -0,0 +1,56 @@
+{
+  "mockBidRequest": {
+    "id": "It is hard to make up ids.",
+    "site": {
+      "page": "http://catsanddogs.com/article/887"
+    },
+    "cur": ["USD"],
+    "imp": [{
+      "id": "Impression id #4",
+      "bidfloorcur": "USD",
+      "video": { "w": 1280, "h": 720, "mimes": ["video/mp4"] },
+      "ext": {
+        "bidder": {
+          "placementId": "64b94ca2b5eb3605e0a0e3be"
+        }
+      }
+    }]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://somecoolurlfor.vox",
+      "heades": {},
+      "body": {
+        "id": "It is hard to make up ids.",
+        "site": {
+          "page": "http://catsanddogs.com/article/887"
+        },
+        "cur": ["USD"],
+        "imp": [{
+          "id": "Impression id #4",
+          "bidfloorcur": "USD",
+          "video": { "w": 1280, "h": 720, "mimes": ["video/mp4"] },
+          "ext": {
+            "bidder": {
+              "placementId": "64b94ca2b5eb3605e0a0e3be"
+            }
+          }
+        }]
+      }
+    },
+
+    "mockResponse": {
+      "status": 500,
+      "headers": {},
+      "body": {}
+    }
+  }],
+
+  "expectedBidResponses": [],
+
+  "expectedMakeBidsErrors": [{
+    "value": "Unexpected status code: 500",
+    "comparison": "regex"
+  }]
+}
\ No newline at end of file
diff --git a/bidadjustment/apply_test.go b/bidadjustment/apply_test.go
index 27daa9c7..c0eb74ab 100644
--- a/bidadjustment/apply_test.go
+++ b/bidadjustment/apply_test.go
@@ -223,12 +223,12 @@ type mockConversions struct {
 	mock.Mock
 }
 
-func (m mockConversions) GetRate(from string, to string) (float64, error) {
+func (m *mockConversions) GetRate(from string, to string) (float64, error) {
 	args := m.Called(from, to)
 	return args.Get(0).(float64), args.Error(1)
 }
 
-func (m mockConversions) GetRates() *map[string]map[string]float64 {
+func (m *mockConversions) GetRates() *map[string]map[string]float64 {
 	args := m.Called()
 	return args.Get(0).(*map[string]map[string]float64)
 }
diff --git a/config/bidderinfo_test.go b/config/bidderinfo_test.go
index 6005178c..f83d942c 100644
--- a/config/bidderinfo_test.go
+++ b/config/bidderinfo_test.go
@@ -244,6 +244,22 @@ func TestBidderInfoValidationPositive(t *testing.T) {
 				},
 			},
 		},
+		"bidderC": BidderInfo{
+			Endpoint: "http://bidderB.com/openrtb2",
+			Maintainer: &MaintainerInfo{
+				Email: "maintainer@bidderA.com",
+			},
+			Capabilities: &CapabilitiesInfo{
+				Site: &PlatformInfo{
+					MediaTypes: []openrtb_ext.BidType{
+						openrtb_ext.BidTypeVideo,
+						openrtb_ext.BidTypeNative,
+						openrtb_ext.BidTypeBanner,
+					},
+				},
+			},
+			AliasOf: "bidderB",
+		},
 	}
 	errs := bidderInfos.validate(make([]error, 0))
 	assert.Len(t, errs, 0, "All bidder infos should be correct")
@@ -467,6 +483,43 @@ func TestBidderInfoValidationNegative(t *testing.T) {
 				errors.New("syncer could not be created, invalid supported endpoint: incorrect"),
 			},
 		},
+		{
+			"Invalid aliases",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+					AliasOf: "bidderB",
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+					AliasOf: "bidderC",
+				},
+			},
+			[]error{
+				errors.New("bidder: bidderB cannot be an alias of an alias: bidderA"),
+				errors.New("bidder: bidderC not found for an alias: bidderB"),
+			},
+		},
 		{
 			"Two bidders, one with incorrect url",
 			BidderInfos{
diff --git a/config/config_test.go b/config/config_test.go
index 402f9ada..30733372 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -885,7 +885,6 @@ func TestUserSyncFromEnv(t *testing.T) {
 	assert.Nil(t, cfg.BidderInfos["bidder2"].Syncer.Redirect)
 	assert.Nil(t, cfg.BidderInfos["bidder2"].Syncer.SupportCORS)
 
-	assert.Nil(t, cfg.BidderInfos["brightroll"].Syncer)
 }
 
 func TestBidderInfoFromEnv(t *testing.T) {
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index 27f84aee..87033f71 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -88,7 +88,7 @@ func TestGoodAmpRequests(t *testing.T) {
 				continue
 			}
 
-			test.storedRequest = map[string]json.RawMessage{tagID: test.BidRequest}
+			test.StoredRequest = map[string]json.RawMessage{tagID: test.BidRequest}
 			test.endpointType = AMP_ENDPOINT
 
 			cfg := &config.Configuration{
@@ -165,7 +165,7 @@ func TestAccountErrors(t *testing.T) {
 		if !assert.NoError(t, json.Unmarshal(fileJsonData, &test), "Failed to unmarshal data from file: %s. Error: %v", tt.filename, err) {
 			continue
 		}
-		test.storedRequest = map[string]json.RawMessage{tt.storedReqID: test.BidRequest}
+		test.StoredRequest = map[string]json.RawMessage{tt.storedReqID: test.BidRequest}
 		test.endpointType = AMP_ENDPOINT
 
 		cfg := &config.Configuration{
@@ -216,6 +216,7 @@ func TestAMPPageInfo(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	request := httptest.NewRequest("GET", fmt.Sprintf("/openrtb2/auction/amp?tag_id=1&curl=%s", url.QueryEscape(page)), nil)
 	recorder := httptest.NewRecorder()
@@ -319,6 +320,7 @@ func TestGDPRConsent(t *testing.T) {
 			openrtb_ext.BuildBidderMap(),
 			empty_fetcher.EmptyFetcher{},
 			hooks.EmptyPlanBuilder{},
+			nil,
 		)
 
 		// Invoke Endpoint
@@ -742,6 +744,7 @@ func TestCCPAConsent(t *testing.T) {
 			openrtb_ext.BuildBidderMap(),
 			empty_fetcher.EmptyFetcher{},
 			hooks.EmptyPlanBuilder{},
+			nil,
 		)
 
 		// Invoke Endpoint
@@ -855,6 +858,7 @@ func TestConsentWarnings(t *testing.T) {
 			openrtb_ext.BuildBidderMap(),
 			empty_fetcher.EmptyFetcher{},
 			hooks.EmptyPlanBuilder{},
+			nil,
 		)
 
 		// Invoke Endpoint
@@ -953,6 +957,7 @@ func TestNewAndLegacyConsentBothProvided(t *testing.T) {
 			openrtb_ext.BuildBidderMap(),
 			empty_fetcher.EmptyFetcher{},
 			hooks.EmptyPlanBuilder{},
+			nil,
 		)
 
 		// Invoke Endpoint
@@ -1007,6 +1012,7 @@ func TestAMPSiteExt(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	request, err := http.NewRequest("GET", "/openrtb2/auction/amp?tag_id=1", nil)
 	if !assert.NoError(t, err) {
@@ -1049,6 +1055,7 @@ func TestAmpBadRequests(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	for requestID := range badRequests {
 		request := httptest.NewRequest("GET", fmt.Sprintf("/openrtb2/auction/amp?tag_id=%s", requestID), nil)
@@ -1082,6 +1089,7 @@ func TestAmpDebug(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 
 	for requestID := range requests {
@@ -1217,6 +1225,7 @@ func TestQueryParamOverrides(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 
 	requestID := "1"
@@ -1374,6 +1383,7 @@ func (s formatOverrideSpec) execute(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 
 	url := fmt.Sprintf("/openrtb2/auction/amp?tag_id=1&debug=1&w=%d&h=%d&ow=%d&oh=%d&ms=%s&account=%s", s.width, s.height, s.overrideWidth, s.overrideHeight, s.multisize, s.account)
@@ -1914,6 +1924,7 @@ func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMe
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	return &actualAmpObject, endpoint
 }
@@ -1966,6 +1977,7 @@ func TestAmpAuctionResponseHeaders(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 
 	for _, test := range testCases {
@@ -2001,6 +2013,7 @@ func TestRequestWithTargeting(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	url, err := url.Parse("/openrtb2/auction/amp")
 	assert.NoError(t, err, "unexpected error received while parsing url")
@@ -2190,7 +2203,7 @@ func TestValidAmpResponseWhenRequestRejected(t *testing.T) {
 			query := request.URL.Query()
 			tagID := query.Get("tag_id")
 
-			test.storedRequest = map[string]json.RawMessage{tagID: test.BidRequest}
+			test.StoredRequest = map[string]json.RawMessage{tagID: test.BidRequest}
 			test.planBuilder = tc.planBuilder
 			test.endpointType = AMP_ENDPOINT
 
diff --git a/endpoints/openrtb2/auction_benchmark_test.go b/endpoints/openrtb2/auction_benchmark_test.go
index 9ad3c768..a3c19ee0 100644
--- a/endpoints/openrtb2/auction_benchmark_test.go
+++ b/endpoints/openrtb2/auction_benchmark_test.go
@@ -111,6 +111,7 @@ func BenchmarkOpenrtbEndpoint(b *testing.B) {
 		nil,
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 
 	b.ResetTimer()
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index c6604fcf..b39f6e03 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -454,7 +454,9 @@ func TestExplicitUserId(t *testing.T) {
 		[]byte{},
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	endpoint(httptest.NewRecorder(), request, nil)
 
@@ -510,7 +512,9 @@ func doBadAliasRequest(t *testing.T, filename string, expectMsg string) {
 		aliasJSON,
 		bidderMap,
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	request := httptest.NewRequest("POST", "/openrtb2/auction", bytes.NewReader(testBidRequest))
 	recorder := httptest.NewRecorder()
@@ -562,7 +566,9 @@ func TestNilExchange(t *testing.T) {
 		[]byte{},
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	if err == nil {
 		t.Errorf("NewEndpoint should return an error when given a nil Exchange.")
@@ -586,7 +592,9 @@ func TestNilValidator(t *testing.T) {
 		[]byte{},
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	if err == nil {
 		t.Errorf("NewEndpoint should return an error when given a nil BidderParamValidator.")
@@ -610,7 +618,9 @@ func TestExchangeError(t *testing.T) {
 		[]byte{},
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	request := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, "site.json")))
 	recorder := httptest.NewRecorder()
@@ -735,7 +745,9 @@ func TestImplicitIPsEndToEnd(t *testing.T) {
 			[]byte{},
 			openrtb_ext.BuildBidderMap(),
 			empty_fetcher.EmptyFetcher{},
-			hooks.EmptyPlanBuilder{})
+			hooks.EmptyPlanBuilder{},
+			nil,
+		)
 
 		httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, test.reqJSONFile)))
 		httpReq.Header.Set("X-Forwarded-For", test.xForwardedForHeader)
@@ -933,7 +945,9 @@ func TestImplicitDNTEndToEnd(t *testing.T) {
 			[]byte{},
 			openrtb_ext.BuildBidderMap(),
 			empty_fetcher.EmptyFetcher{},
-			hooks.EmptyPlanBuilder{})
+			hooks.EmptyPlanBuilder{},
+			nil,
+		)
 
 		httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, test.reqJSONFile)))
 		httpReq.Header.Set("DNT", test.dntHeader)
@@ -1144,6 +1158,7 @@ func TestStoredRequests(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	testStoreVideoAttr := []bool{true, true, false, false, false}
@@ -1517,6 +1532,7 @@ func TestValidateRequest(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	testCases := []struct {
@@ -1611,7 +1627,7 @@ func TestValidateRequest(t *testing.T) {
 							Ext: []byte(`{"appnexus":{"placementId": 12345678}}`),
 						},
 					},
-					Ext: []byte(`{"prebid":{"aliases":{"brightroll":"appnexus"}, "aliasgvlids":{"pubmatic1":1}}}`),
+					Ext: []byte(`{"prebid":{"aliases":{"yahoossp":"appnexus"}, "aliasgvlids":{"pubmatic1":1}}}`),
 				},
 			},
 			givenIsAmp:            false,
@@ -1642,11 +1658,11 @@ func TestValidateRequest(t *testing.T) {
 							Ext: []byte(`{"appnexus":{"placementId": 12345678}}`),
 						},
 					},
-					Ext: []byte(`{"prebid":{"aliases":{"brightroll":"appnexus"}, "aliasgvlids":{"brightroll":0}}}`),
+					Ext: []byte(`{"prebid":{"aliases":{"yahoossp":"appnexus"}, "aliasgvlids":{"yahoossp":0}}}`),
 				},
 			},
 			givenIsAmp:            false,
-			expectedErrorList:     []error{errors.New("request.ext.prebid.aliasgvlids. Invalid vendorId 0 for alias: brightroll. Choose a different vendorId, or remove this entry.")},
+			expectedErrorList:     []error{errors.New("request.ext.prebid.aliasgvlids. Invalid vendorId 0 for alias: yahoossp. Choose a different vendorId, or remove this entry.")},
 			expectedChannelObject: &openrtb_ext.ExtRequestPrebidChannel{Name: appChannel, Version: ""},
 		},
 		{
@@ -1673,7 +1689,7 @@ func TestValidateRequest(t *testing.T) {
 							Ext: []byte(`{"appnexus":{"placementId": 12345678}}`),
 						},
 					},
-					Ext: []byte(`{"prebid":{"aliases":{"brightroll":"appnexus"}, "aliasgvlids":{"brightroll":1}}}`),
+					Ext: []byte(`{"prebid":{"aliases":{"yahoossp":"appnexus"}, "aliasgvlids":{"yahoossp":1}}}`),
 				},
 			},
 			givenIsAmp:            false,
@@ -2235,6 +2251,7 @@ func TestSetIntegrationType(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	testCases := []struct {
@@ -2300,6 +2317,7 @@ func TestStoredRequestGenerateUuid(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	req := &openrtb2.BidRequest{}
@@ -2403,6 +2421,7 @@ func TestOversizedRequest(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody))
@@ -2441,6 +2460,7 @@ func TestRequestSizeEdgeCase(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody))
@@ -2473,6 +2493,7 @@ func TestNoEncoding(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	request := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, "site.json")))
 	recorder := httptest.NewRecorder()
@@ -2557,6 +2578,7 @@ func TestContentType(t *testing.T) {
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	)
 	request := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, "site.json")))
 	recorder := httptest.NewRecorder()
@@ -2777,6 +2799,7 @@ func TestValidateImpExt(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	for _, group := range testGroups {
@@ -2829,6 +2852,7 @@ func TestCurrencyTrunc(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	ui := int64(1)
@@ -2876,6 +2900,7 @@ func TestCCPAInvalid(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	ui := int64(1)
@@ -2927,6 +2952,7 @@ func TestNoSaleInvalid(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	ui := int64(1)
@@ -2981,6 +3007,7 @@ func TestValidateSourceTID(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	ui := int64(1)
@@ -3025,6 +3052,7 @@ func TestSChainInvalid(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	ui := int64(1)
@@ -3520,6 +3548,7 @@ func TestEidPermissionsInvalid(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	ui := int64(1)
@@ -3768,7 +3797,9 @@ func TestIOS14EndToEnd(t *testing.T) {
 		[]byte{},
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(validRequest(t, "app-ios140-no-ifa.json")))
 
@@ -3834,6 +3865,7 @@ func TestAuctionWarnings(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 	for _, test := range testCases {
 		t.Run(test.name, func(t *testing.T) {
@@ -3879,6 +3911,7 @@ func TestParseRequestParseImpInfoError(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
@@ -3958,6 +3991,7 @@ func TestParseGzipedRequest(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
@@ -4451,7 +4485,9 @@ func TestAuctionResponseHeaders(t *testing.T) {
 		[]byte{},
 		openrtb_ext.BuildBidderMap(),
 		empty_fetcher.EmptyFetcher{},
-		hooks.EmptyPlanBuilder{})
+		hooks.EmptyPlanBuilder{},
+		nil,
+	)
 
 	for _, test := range testCases {
 		httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(test.requestBody))
@@ -4555,6 +4591,7 @@ func TestParseRequestMergeBidderParams(t *testing.T) {
 				hardcodedResponseIPValidator{response: true},
 				empty_fetcher.EmptyFetcher{},
 				hooks.EmptyPlanBuilder{},
+				nil,
 			}
 
 			hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
@@ -4657,6 +4694,7 @@ func TestParseRequestStoredResponses(t *testing.T) {
 				hardcodedResponseIPValidator{response: true},
 				&mockStoredResponseFetcher{mockStoredResponses},
 				hooks.EmptyPlanBuilder{},
+				nil,
 			}
 
 			hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
@@ -4744,6 +4782,7 @@ func TestParseRequestStoredBidResponses(t *testing.T) {
 				hardcodedResponseIPValidator{response: true},
 				&mockStoredResponseFetcher{mockStoredBidResponses},
 				hooks.EmptyPlanBuilder{},
+				nil,
 			}
 
 			hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
@@ -4780,6 +4819,7 @@ func TestValidateStoredResp(t *testing.T) {
 		hardcodedResponseIPValidator{response: true},
 		&mockStoredResponseFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	testCases := []struct {
@@ -5592,6 +5632,7 @@ func TestParseRequestMultiBid(t *testing.T) {
 				hardcodedResponseIPValidator{response: true},
 				empty_fetcher.EmptyFetcher{},
 				hooks.EmptyPlanBuilder{},
+				nil,
 			}
 
 			hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
diff --git a/endpoints/openrtb2/test_utils.go b/endpoints/openrtb2/test_utils.go
index afe88397..401fbf62 100644
--- a/endpoints/openrtb2/test_utils.go
+++ b/endpoints/openrtb2/test_utils.go
@@ -76,7 +76,7 @@ type testCase struct {
 	ExpectedBidResponse json.RawMessage `json:"expectedBidResponse"`
 
 	// "/openrtb2/amp" endpoint JSON test info
-	storedRequest       map[string]json.RawMessage `json:"mockAmpStoredRequest"`
+	StoredRequest       map[string]json.RawMessage `json:"mockAmpStoredRequest"`
 	StoredResponse      map[string]json.RawMessage `json:"mockAmpStoredResponse"`
 	ExpectedAmpResponse json.RawMessage            `json:"expectedAmpResponse"`
 }
@@ -1265,8 +1265,8 @@ func buildTestEndpoint(test testCase, cfg *config.Configuration) (httprouter.Han
 	testExchange, mockBidServersArray := buildTestExchange(test.Config, adapterMap, mockBidServersArray, mockCurrencyRatesServer, bidderInfos, cfg, met, mockFetcher)
 
 	var storedRequestFetcher stored_requests.Fetcher
-	if len(test.storedRequest) > 0 {
-		storedRequestFetcher = &mockAmpStoredReqFetcher{test.storedRequest}
+	if len(test.StoredRequest) > 0 {
+		storedRequestFetcher = &mockAmpStoredReqFetcher{test.StoredRequest}
 	} else {
 		storedRequestFetcher = &mockStoredReqFetcher{}
 	}
@@ -1290,7 +1290,7 @@ func buildTestEndpoint(test testCase, cfg *config.Configuration) (httprouter.Han
 		planBuilder = hooks.EmptyPlanBuilder{}
 	}
 
-	var endpointBuilder func(uuidutil.UUIDGenerator, exchange.Exchange, openrtb_ext.BidderParamValidator, stored_requests.Fetcher, stored_requests.AccountFetcher, *config.Configuration, metrics.MetricsEngine, analytics.PBSAnalyticsModule, map[string]string, []byte, map[string]openrtb_ext.BidderName, stored_requests.Fetcher, hooks.ExecutionPlanBuilder) (httprouter.Handle, error)
+	var endpointBuilder func(uuidutil.UUIDGenerator, exchange.Exchange, openrtb_ext.BidderParamValidator, stored_requests.Fetcher, stored_requests.AccountFetcher, *config.Configuration, metrics.MetricsEngine, analytics.PBSAnalyticsModule, map[string]string, []byte, map[string]openrtb_ext.BidderName, stored_requests.Fetcher, hooks.ExecutionPlanBuilder, *exchange.TmaxAdjustmentsPreprocessed) (httprouter.Handle, error)
 
 	switch test.endpointType {
 	case AMP_ENDPOINT:
@@ -1313,6 +1313,7 @@ func buildTestEndpoint(test testCase, cfg *config.Configuration) (httprouter.Han
 		bidderMap,
 		storedResponseFetcher,
 		planBuilder,
+		nil,
 	)
 
 	return endpoint, testExchange.(*exchangeTestWrapper), mockBidServersArray, mockCurrencyRatesServer, err
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index 496a2ac8..1f28efb8 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -1225,6 +1225,7 @@ func mockDepsWithMetrics(t *testing.T, ex *mockExchangeVideo) (*endpointDeps, *m
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 	return deps, metrics, mockModule
 }
@@ -1270,6 +1271,7 @@ func mockDeps(t *testing.T, ex *mockExchangeVideo) *endpointDeps {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 }
 
@@ -1293,6 +1295,7 @@ func mockDepsAppendBidderNames(t *testing.T, ex *mockExchangeAppendBidderNames)
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	return deps
@@ -1318,6 +1321,7 @@ func mockDepsNoBids(t *testing.T, ex *mockExchangeVideoNoBids) *endpointDeps {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 		hooks.EmptyPlanBuilder{},
+		nil,
 	}
 
 	return edep
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index 9176041e..65bc2655 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -50,7 +50,7 @@ func TestSetUIDEndpoint(t *testing.T) {
 			description:            "Set uid for valid bidder",
 		},
 		{
-			uri:                    "/setuid?bidder=adnxs&uid=123",
+			uri:                    "/setuid?bidder=appnexus&uid=123",
 			syncersBidderNameToKey: map[string]string{"appnexus": "adnxs"},
 			existingSyncs:          nil,
 			gdprAllowsHostCookies:  true,
diff --git a/exchange/adapter_util_test.go b/exchange/adapter_util_test.go
index 2dd0fd04..2f3c8e9a 100644
--- a/exchange/adapter_util_test.go
+++ b/exchange/adapter_util_test.go
@@ -67,6 +67,13 @@ func TestBuildAdapters(t *testing.T) {
 				errors.New("unknown: unknown bidder"),
 			},
 		},
+		{
+			description: "Alias feature disabled",
+			bidderInfos: map[string]config.BidderInfo{"appNexus": {AliasOf: "rubicon"}},
+			expectedErrors: []error{
+				errors.New("This feature is currently under development"),
+			},
+		},
 	}
 
 	cfg := &config.Configuration{}
@@ -215,6 +222,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 				"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
 				"verizonmedia":   `Bidder "verizonmedia" is no longer available in Prebid Server. Please update your configuration.`,
+				"brightroll":     `Bidder "brightroll" is no longer available in Prebid Server. Please update your configuration.`,
 			},
 		},
 		{
@@ -229,6 +237,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 				"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
 				"verizonmedia":   `Bidder "verizonmedia" is no longer available in Prebid Server. Please update your configuration.`,
+				"brightroll":     `Bidder "brightroll" is no longer available in Prebid Server. Please update your configuration.`,
 			},
 		},
 		{
@@ -244,6 +253,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 				"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
 				"verizonmedia":   `Bidder "verizonmedia" is no longer available in Prebid Server. Please update your configuration.`,
+				"brightroll":     `Bidder "brightroll" is no longer available in Prebid Server. Please update your configuration.`,
 			},
 		},
 		{
@@ -259,6 +269,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 				"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
 				"verizonmedia":   `Bidder "verizonmedia" is no longer available in Prebid Server. Please update your configuration.`,
+				"brightroll":     `Bidder "brightroll" is no longer available in Prebid Server. Please update your configuration.`,
 			},
 		},
 	}
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index 9d36808c..3eeb3e90 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -3063,3 +3063,79 @@ func TestGetBidType(t *testing.T) {
 		})
 	}
 }
+
+type mockBidderTmaxCtx struct {
+	startTime, deadline time.Time
+	ok                  bool
+}
+
+func (m *mockBidderTmaxCtx) Deadline() (deadline time.Time, _ bool) {
+	return m.deadline, m.ok
+}
+func (m *mockBidderTmaxCtx) RemainingDurationMS(deadline time.Time) int64 {
+	return deadline.Sub(m.startTime).Milliseconds()
+}
+
+func TestUpdateBidderTmax(t *testing.T) {
+	respStatus := 200
+	respBody := "{\"bid\":false}"
+	server := httptest.NewServer(mockHandler(respStatus, "getBody", respBody))
+	defer server.Close()
+
+	requestHeaders := http.Header{}
+	requestHeaders.Add("Content-Type", "application/json")
+
+	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
+	var requestTmax int64 = 700
+
+	bidderReq := BidderRequest{
+		BidRequest: &openrtb2.BidRequest{Imp: []openrtb2.Imp{{ID: "impId"}}, TMax: requestTmax},
+		BidderName: "test",
+	}
+	extraInfo := &adapters.ExtraRequestInfo{}
+
+	tests := []struct {
+		description     string
+		requestTmax     int64
+		tmaxAdjustments *TmaxAdjustmentsPreprocessed
+		assertFn        func(actualTmax int64) bool
+	}{
+		{
+			description:     "tmax-is-not-enabled",
+			requestTmax:     requestTmax,
+			tmaxAdjustments: &TmaxAdjustmentsPreprocessed{IsEnforced: false},
+			assertFn: func(actualTmax int64) bool {
+				return requestTmax == actualTmax
+			},
+		},
+		{
+			description:     "updates-bidder-tmax",
+			requestTmax:     requestTmax,
+			tmaxAdjustments: &TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 50, PBSResponsePreparationDuration: 50},
+			assertFn: func(actualTmax int64) bool {
+				return requestTmax > actualTmax
+			},
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.description, func(t *testing.T) {
+			bidderImpl := &goodSingleBidder{
+				httpRequest: &adapters.RequestData{
+					Method:  "POST",
+					Uri:     server.URL,
+					Body:    []byte("{\"key\":\"val\"}"),
+					Headers: http.Header{},
+				},
+				bidResponse: &adapters.BidderResponse{},
+			}
+
+			ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(50*time.Millisecond))
+			defer cancel()
+			bidReqOptions := bidRequestOptions{tmaxAdjustments: test.tmaxAdjustments}
+			bidder := AdaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: false}, "")
+			_, _, errs := bidder.requestBid(ctx, bidderReq, currencyConverter.Rates(), extraInfo, &adscert.NilSigner{}, bidReqOptions, openrtb_ext.ExtAlternateBidderCodes{}, &hookexecution.EmptyHookExecutor{}, nil)
+			assert.Empty(t, errs)
+			assert.True(t, test.assertFn(bidderImpl.bidRequest.TMax))
+		})
+	}
+}
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 2a35ef57..8e7ba80b 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -379,7 +379,7 @@ func TestDebugBehaviour(t *testing.T) {
 		// Assert no HoldAuction error
 		assert.NoErrorf(t, err, "%s. ex.HoldAuction returned an error: %v \n", test.desc, err)
 		assert.NotNilf(t, outBidResponse.Ext, "%s. outBidResponse.Ext should not be nil \n", test.desc)
-
+		assert.False(t, auctionRequest.BidderResponseStartTime.IsZero())
 		actualExt := &openrtb_ext.ExtBidResponse{}
 		err = json.Unmarshal(outBidResponse.Ext, actualExt)
 		assert.NoErrorf(t, err, "%s. \"ext\" JSON field could not be unmarshaled. err: \"%v\" \n outBidResponse.Ext: \"%s\" \n", test.desc, err, outBidResponse.Ext)
@@ -540,6 +540,7 @@ func TestTwoBiddersDebugDisabledAndEnabled(t *testing.T) {
 		// Assert no HoldAuction err
 		assert.NoErrorf(t, err, "ex.HoldAuction returned an err")
 		assert.NotNilf(t, outBidResponse.Ext, "outBidResponse.Ext should not be nil")
+		assert.False(t, auctionRequest.BidderResponseStartTime.IsZero())
 
 		actualExt := &openrtb_ext.ExtBidResponse{}
 		err = json.Unmarshal(outBidResponse.Ext, actualExt)
@@ -715,6 +716,7 @@ func TestOverrideWithCustomCurrency(t *testing.T) {
 
 		// Assertions
 		assert.NoErrorf(t, err, "%s. HoldAuction error: %v \n", test.desc, err)
+		assert.False(t, auctionRequest.BidderResponseStartTime.IsZero())
 
 		if test.expected.numBids > 0 {
 			// Assert out currency
@@ -1362,6 +1364,7 @@ func TestReturnCreativeEndToEnd(t *testing.T) {
 				continue
 			} else {
 				assert.NoErrorf(t, err, "%s: %s. HoldAuction error: %v \n", testGroup.groupDesc, test.desc, err)
+				assert.False(t, auctionRequest.BidderResponseStartTime.IsZero())
 			}
 
 			// Assert returned bid
@@ -5143,6 +5146,7 @@ func TestOverrideConfigAlternateBidderCodesWithRequestValues(t *testing.T) {
 		// Assertions
 		assert.NoErrorf(t, err, "%s. HoldAuction error: %v \n", test.desc, err)
 		assert.NotNil(t, outBidResponse)
+		assert.False(t, auctionRequest.BidderResponseStartTime.IsZero())
 
 		// So 2 seatBids are expected as,
 		// the default "" and "pubmatic" bids will be in one seat and the extra-bids "groupm"/"appnexus"/"ix" in another seat.
@@ -5569,6 +5573,7 @@ func TestModulesCanBeExecutedForMultipleBiddersSimultaneously(t *testing.T) {
 	_, err := e.HoldAuction(context.Background(), auctionRequest, &DebugLog{})
 	// Assert no HoldAuction err
 	assert.NoErrorf(t, err, "ex.HoldAuction returned an err")
+	assert.False(t, auctionRequest.BidderResponseStartTime.IsZero())
 
 	// check stage outcomes
 	assert.Equal(t, len(exec.GetOutcomes()), len(e.adapterMap), "stage outcomes append operation failed")
diff --git a/exchange/tmax_adjustments_test.go b/exchange/tmax_adjustments_test.go
new file mode 100644
index 00000000..7e6a02ab
--- /dev/null
+++ b/exchange/tmax_adjustments_test.go
@@ -0,0 +1,108 @@
+package exchange
+
+import (
+	"testing"
+	"time"
+
+	"github.com/prebid/prebid-server/config"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetBidderTmax(t *testing.T) {
+	var (
+		requestTmaxMS               int64 = 700
+		bidderNetworkLatencyBuffer  uint  = 50
+		responsePreparationDuration uint  = 60
+	)
+	requestTmaxNS := requestTmaxMS * int64(time.Millisecond)
+	startTime := time.Date(2023, 5, 30, 1, 0, 0, 0, time.UTC)
+	deadline := time.Date(2023, 5, 30, 1, 0, 0, int(requestTmaxNS), time.UTC)
+	ctx := &mockBidderTmaxCtx{startTime: startTime, deadline: deadline, ok: true}
+	tests := []struct {
+		description     string
+		ctx             bidderTmaxContext
+		requestTmax     int64
+		expectedTmax    int64
+		tmaxAdjustments TmaxAdjustmentsPreprocessed
+	}{
+		{
+			description:     "returns-requestTmax-when-IsEnforced-is-false",
+			ctx:             ctx,
+			requestTmax:     requestTmaxMS,
+			tmaxAdjustments: TmaxAdjustmentsPreprocessed{IsEnforced: false},
+			expectedTmax:    requestTmaxMS,
+		},
+		{
+			description:     "returns-requestTmax-when-BidderResponseDurationMin-is-not-set",
+			ctx:             ctx,
+			requestTmax:     requestTmaxMS,
+			tmaxAdjustments: TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 0},
+			expectedTmax:    requestTmaxMS,
+		},
+		{
+			description:     "returns-requestTmax-when-BidderNetworkLatencyBuffer-and-PBSResponsePreparationDuration-is-not-set",
+			ctx:             ctx,
+			requestTmax:     requestTmaxMS,
+			tmaxAdjustments: TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 0, PBSResponsePreparationDuration: 0},
+			expectedTmax:    requestTmaxMS,
+		},
+		{
+			description:     "returns-requestTmax-when-context-deadline-is-not-set",
+			ctx:             &mockBidderTmaxCtx{ok: false},
+			requestTmax:     requestTmaxMS,
+			tmaxAdjustments: TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 50, PBSResponsePreparationDuration: 60},
+			expectedTmax:    requestTmaxMS,
+		},
+		{
+			description:     "returns-remaing-duration-by-subtracting-BidderNetworkLatencyBuffer-and-PBSResponsePreparationDuration",
+			ctx:             ctx,
+			requestTmax:     requestTmaxMS,
+			tmaxAdjustments: TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: bidderNetworkLatencyBuffer, PBSResponsePreparationDuration: responsePreparationDuration},
+			expectedTmax:    ctx.RemainingDurationMS(deadline) - int64(bidderNetworkLatencyBuffer) - int64(responsePreparationDuration),
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.description, func(t *testing.T) {
+			assert.Equal(t, test.expectedTmax, getBidderTmax(test.ctx, test.requestTmax, test.tmaxAdjustments))
+		})
+	}
+}
+
+func TestProcessTMaxAdjustments(t *testing.T) {
+	tests := []struct {
+		description     string
+		expected        *TmaxAdjustmentsPreprocessed
+		tmaxAdjustments config.TmaxAdjustments
+	}{
+		{
+			description:     "returns-nil-when-tmax-is-not-enabled",
+			tmaxAdjustments: config.TmaxAdjustments{Enabled: false},
+			expected:        nil,
+		},
+		{
+			description:     "BidderResponseDurationMin-is-not-set",
+			tmaxAdjustments: config.TmaxAdjustments{Enabled: true, BidderResponseDurationMin: 0, BidderNetworkLatencyBuffer: 10, PBSResponsePreparationDuration: 20},
+			expected:        &TmaxAdjustmentsPreprocessed{IsEnforced: false, BidderResponseDurationMin: 0, BidderNetworkLatencyBuffer: 10, PBSResponsePreparationDuration: 20},
+		},
+		{
+			description:     "BidderNetworkLatencyBuffer-and-PBSResponsePreparationDuration-are-not-set",
+			tmaxAdjustments: config.TmaxAdjustments{Enabled: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 0, PBSResponsePreparationDuration: 0},
+			expected:        &TmaxAdjustmentsPreprocessed{IsEnforced: false, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 0, PBSResponsePreparationDuration: 0},
+		},
+		{
+			description:     "BidderNetworkLatencyBuffer-is-not-set",
+			tmaxAdjustments: config.TmaxAdjustments{Enabled: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 0, PBSResponsePreparationDuration: 10},
+			expected:        &TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 0, PBSResponsePreparationDuration: 10},
+		},
+		{
+			description:     "PBSResponsePreparationDuration-is-not-set",
+			tmaxAdjustments: config.TmaxAdjustments{Enabled: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 10, PBSResponsePreparationDuration: 0},
+			expected:        &TmaxAdjustmentsPreprocessed{IsEnforced: true, BidderResponseDurationMin: 100, BidderNetworkLatencyBuffer: 10, PBSResponsePreparationDuration: 0},
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.description, func(t *testing.T) {
+			assert.Equal(t, test.expected, ProcessTMaxAdjustments(test.tmaxAdjustments))
+		})
+	}
+}
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 973edc53..b62e9597 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -74,8 +74,6 @@ func assertReq(t *testing.T, bidderRequests []BidderRequest,
 	assert.NotEqual(t, bidderRequests, 0, "cleanOpenRTBRequest should split request into individual bidder requests")
 
 	// assert for PI data
-	// Both appnexus and brightroll should be allowed since brightroll
-	// is used as an alias for appnexus in the test request
 	for _, req := range bidderRequests {
 		if !applyCOPPA && consentedVendors[req.BidderName.String()] {
 			assert.NotEqual(t, req.BidRequest.User.BuyerUID, "", "cleanOpenRTBRequest shouldn't clean PI data as per COPPA or for a consented vendor as per GDPR or per CCPA")
@@ -459,7 +457,7 @@ func TestCleanOpenRTBRequests(t *testing.T) {
 			bidReqAssertions: assertReq,
 			hasError:         false,
 			applyCOPPA:       false,
-			consentedVendors: map[string]bool{"appnexus": true, "brightroll": true},
+			consentedVendors: map[string]bool{"appnexus": true},
 		},
 	}
 
@@ -508,13 +506,6 @@ func TestCleanOpenRTBRequestsWithFPD(t *testing.T) {
 	}
 	fpd[openrtb_ext.BidderName("rubicon")] = &apnFpd
 
-	brightrollFpd := firstpartydata.ResolvedFirstPartyData{
-		Site: &openrtb2.Site{Name: "fpdBrightrollSite"},
-		App:  &openrtb2.App{Name: "fpdBrightrollApp"},
-		User: &openrtb2.User{Keywords: "fpdBrightrollUser"},
-	}
-	fpd[openrtb_ext.BidderName("brightroll")] = &brightrollFpd
-
 	emptyTCF2Config := gdpr.NewTCF2Config(config.TCF2{}, config.AccountGDPR{})
 
 	testCases := []struct {
@@ -2580,9 +2571,9 @@ func newAdapterAliasBidRequest(t *testing.T) *openrtb2.BidRequest {
 					H: 600,
 				}},
 			},
-			Ext: json.RawMessage(`{"appnexus": {"placementId": 1},"brightroll": {"placementId": 105}}`),
+			Ext: json.RawMessage(`{"appnexus": {"placementId": 1},"somealias": {"placementId": 105}}`),
 		}},
-		Ext: json.RawMessage(`{"prebid":{"aliases":{"brightroll":"appnexus"}}}`),
+		Ext: json.RawMessage(`{"prebid":{"aliases":{"somealias":"appnexus"}}}`),
 	}
 }
 
@@ -3196,17 +3187,17 @@ func Test_parseAliasesGVLIDs(t *testing.T) {
 			"AliasGVLID Parsed Correctly",
 			args{
 				orig: &openrtb2.BidRequest{
-					Ext: json.RawMessage(`{"prebid":{"aliases":{"brightroll":"appnexus"}, "aliasgvlids":{"brightroll":1}}}`),
+					Ext: json.RawMessage(`{"prebid":{"aliases":{"somealiascode":"appnexus"}, "aliasgvlids":{"somealiascode":1}}}`),
 				},
 			},
-			map[string]uint16{"brightroll": 1},
+			map[string]uint16{"somealiascode": 1},
 			false,
 		},
 		{
 			"AliasGVLID parsing error",
 			args{
 				orig: &openrtb2.BidRequest{
-					Ext: json.RawMessage(`{"prebid":{"aliases":{"brightroll":"appnexus"}, "aliasgvlids": {"brightroll":"abc"}`),
+					Ext: json.RawMessage(`{"prebid":{"aliases":{"somealiascode":"appnexus"}, "aliasgvlids": {"somealiascode":"abc"}`),
 				},
 			},
 			nil,
@@ -3216,7 +3207,7 @@ func Test_parseAliasesGVLIDs(t *testing.T) {
 			"Invalid AliasGVLID",
 			args{
 				orig: &openrtb2.BidRequest{
-					Ext: json.RawMessage(`{"prebid":{"aliases":{"brightroll":"appnexus"}, "aliasgvlids":"abc"}`),
+					Ext: json.RawMessage(`{"prebid":{"aliases":{"somealiascode":"appnexus"}, "aliasgvlids":"abc"}`),
 				},
 			},
 			nil,
@@ -3226,7 +3217,7 @@ func Test_parseAliasesGVLIDs(t *testing.T) {
 			"Missing AliasGVLID",
 			args{
 				orig: &openrtb2.BidRequest{
-					Ext: json.RawMessage(`{"prebid":{"aliases":{"brightroll":"appnexus"}}`),
+					Ext: json.RawMessage(`{"prebid":{"aliases":{"somealiascode":"appnexus"}}`),
 				},
 			},
 			nil,
diff --git a/usersync/syncer_test.go b/usersync/syncer_test.go
index 6e727c3a..c309b899 100644
--- a/usersync/syncer_test.go
+++ b/usersync/syncer_test.go
@@ -26,6 +26,7 @@ func TestNewSyncer(t *testing.T) {
 	testCases := []struct {
 		description         string
 		givenKey            string
+		givenBidderName     string
 		givenIFrameConfig   *config.SyncerEndpoint
 		givenRedirectConfig *config.SyncerEndpoint
 		givenExternalURL    string
@@ -37,6 +38,7 @@ func TestNewSyncer(t *testing.T) {
 		{
 			description:         "Missing Key",
 			givenKey:            "",
+			givenBidderName:     "",
 			givenIFrameConfig:   iframeConfig,
 			givenRedirectConfig: nil,
 			expectedError:       "key is required",
@@ -44,6 +46,7 @@ func TestNewSyncer(t *testing.T) {
 		{
 			description:         "Missing Endpoints",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenIFrameConfig:   nil,
 			givenRedirectConfig: nil,
 			expectedError:       "at least one endpoint (iframe and/or redirect) is required",
@@ -51,6 +54,7 @@ func TestNewSyncer(t *testing.T) {
 		{
 			description:         "IFrame & Redirect Endpoints",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenIFrameConfig:   iframeConfig,
 			givenRedirectConfig: redirectConfig,
 			expectedDefault:     SyncTypeIFrame,
@@ -60,13 +64,15 @@ func TestNewSyncer(t *testing.T) {
 		{
 			description:         "IFrame - Parse Error",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenIFrameConfig:   errParseConfig,
 			givenRedirectConfig: nil,
-			expectedError:       "iframe template: a_usersync_url:1: function \"malformed\" not defined",
+			expectedError:       "iframe template: biddera_usersync_url:1: function \"malformed\" not defined",
 		},
 		{
 			description:         "IFrame - Validation Error",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenIFrameConfig:   errInvalidConfig,
 			givenRedirectConfig: nil,
 			expectedError:       "iframe composed url: \"notAURL:http%3A%2F%2Fhost.com%2Fhost\" is invalid",
@@ -74,13 +80,15 @@ func TestNewSyncer(t *testing.T) {
 		{
 			description:         "Redirect - Parse Error",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenIFrameConfig:   nil,
 			givenRedirectConfig: errParseConfig,
-			expectedError:       "redirect template: a_usersync_url:1: function \"malformed\" not defined",
+			expectedError:       "redirect template: biddera_usersync_url:1: function \"malformed\" not defined",
 		},
 		{
 			description:         "Redirect - Validation Error",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenIFrameConfig:   nil,
 			givenRedirectConfig: errInvalidConfig,
 			expectedError:       "redirect composed url: \"notAURL:http%3A%2F%2Fhost.com%2Fhost\" is invalid",
@@ -88,6 +96,7 @@ func TestNewSyncer(t *testing.T) {
 		{
 			description:         "Syncer Level External URL",
 			givenKey:            "a",
+			givenBidderName:     "bidderA",
 			givenExternalURL:    "http://syncer.com",
 			givenIFrameConfig:   iframeConfig,
 			givenRedirectConfig: redirectConfig,
@@ -106,7 +115,7 @@ func TestNewSyncer(t *testing.T) {
 			ExternalURL: test.givenExternalURL,
 		}
 
-		result, err := NewSyncer(hostConfig, syncerConfig)
+		result, err := NewSyncer(hostConfig, syncerConfig, test.givenBidderName)
 
 		if test.expectedError == "" {
 			assert.NoError(t, err, test.description+":err")
@@ -196,7 +205,7 @@ func TestBuildTemplate(t *testing.T) {
 			expectedRendered: "hasNoComposedMacros,gdpr=A",
 		},
 		{
-			description: "All Composed Macros",
+			description: "All Composed Macros - SyncerKey",
 			givenSyncerEndpoint: config.SyncerEndpoint{
 				URL:         "https://bidder.com/sync?redirect={{.RedirectURL}}",
 				RedirectURL: "{{.ExternalURL}}/setuid?bidder={{.SyncerKey}}&f={{.SyncType}}&gdpr={{.GDPR}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&uid={{.UserMacro}}",
@@ -205,6 +214,16 @@ func TestBuildTemplate(t *testing.T) {
 			},
 			expectedRendered: "https://bidder.com/sync?redirect=http%3A%2F%2Fsyncer.com%2Fsetuid%3Fbidder%3DanyKey%26f%3Dx%26gdpr%3DA%26gpp%3DD%26gpp_sid%3D1%26uid%3D%24UID%24",
 		},
+		{
+			description: "All Composed Macros - BidderName",
+			givenSyncerEndpoint: config.SyncerEndpoint{
+				URL:         "https://bidder.com/sync?redirect={{.RedirectURL}}",
+				RedirectURL: "{{.ExternalURL}}/setuid?bidder={{.BidderName}}&f={{.SyncType}}&gdpr={{.GDPR}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&uid={{.UserMacro}}",
+				ExternalURL: "http://syncer.com",
+				UserMacro:   "$UID$",
+			},
+			expectedRendered: "https://bidder.com/sync?redirect=http%3A%2F%2Fsyncer.com%2Fsetuid%3Fbidder%3DanyKey%26f%3Dx%26gdpr%3DA%26gpp%3DD%26gpp_sid%3D1%26uid%3D%24UID%24",
+		},
 		{
 			description: "Redirect URL + External URL From Host",
 			givenSyncerEndpoint: config.SyncerEndpoint{
diff --git a/usersync/syncersbuilder_test.go b/usersync/syncersbuilder_test.go
index b3672a50..fbc18639 100644
--- a/usersync/syncersbuilder_test.go
+++ b/usersync/syncersbuilder_test.go
@@ -48,7 +48,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAPopulated},
 			expectedIFramesURLs: map[string]string{
-				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fa%2Fhost",
+				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder1%2Fhost",
 			},
 		},
 		{
@@ -64,7 +64,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAError},
 			expectedErrors: []string{
-				"cannot create syncer for bidder bidder1 with key a: iframe template: a_usersync_url:1: function \"xRedirectURL\" not defined",
+				"cannot create syncer for bidder bidder1 with key a: iframe template: bidder1_usersync_url:1: function \"xRedirectURL\" not defined",
 			},
 		},
 		{
@@ -72,8 +72,8 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAPopulated, "bidder2": infoKeyBPopulated},
 			expectedIFramesURLs: map[string]string{
-				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fa%2Fhost",
-				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fb%2Fhost",
+				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder1%2Fhost",
+				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder2%2Fhost",
 			},
 		},
 		{
@@ -81,8 +81,8 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAPopulated, "bidder2": infoKeyAEmpty},
 			expectedIFramesURLs: map[string]string{
-				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fa%2Fhost",
-				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fa%2Fhost",
+				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder1%2Fhost",
+				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder2%2Fhost",
 			},
 		},
 		{
@@ -106,7 +106,8 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAEmpty, "bidder2": infoKeyAError},
 			expectedErrors: []string{
-				"cannot create syncer for bidder bidder2 with key a: iframe template: a_usersync_url:1: function \"xRedirectURL\" not defined",
+				"cannot create syncer for bidder bidder2 with key a: iframe template: bidder1_usersync_url:1: function \"xRedirectURL\" not defined",
+				"cannot create syncer for bidder bidder2 with key a: iframe template: bidder2_usersync_url:1: function \"xRedirectURL\" not defined",
 			},
 		},
 		{
@@ -114,7 +115,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": {}, "bidder2": infoKeyBPopulated},
 			expectedIFramesURLs: map[string]string{
-				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fb%2Fhost",
+				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder2%2Fhost",
 			},
 		},
 		{
@@ -122,7 +123,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyADisabled, "bidder2": infoKeyBPopulated},
 			expectedIFramesURLs: map[string]string{
-				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fb%2Fhost",
+				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder2%2Fhost",
 			},
 		},
 		{
@@ -130,7 +131,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyASupportsOnly, "bidder2": infoKeyBPopulated},
 			expectedIFramesURLs: map[string]string{
-				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fb%2Fhost",
+				"bidder2": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhost.com%2Fbidder2%2Fhost",
 			},
 		},
 		{
@@ -138,7 +139,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      hostConfig,
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAError, "bidder2": infoKeyBEmpty},
 			expectedErrors: []string{
-				"cannot create syncer for bidder bidder1 with key a: iframe template: a_usersync_url:1: function \"xRedirectURL\" not defined",
+				"cannot create syncer for bidder bidder1 with key a: iframe template: bidder1_usersync_url:1: function \"xRedirectURL\" not defined",
 				"cannot create syncer for bidder bidder2 with key b: at least one endpoint (iframe and/or redirect) is required",
 			},
 		},
@@ -147,7 +148,7 @@ func TestBuildSyncers(t *testing.T) {
 			givenConfig:      config.Configuration{ExternalURL: "http://host.com", UserSync: config.UserSync{ExternalURL: "http://hostoverride.com", RedirectURL: "{{.ExternalURL}}/{{.SyncerKey}}/host"}},
 			givenBidderInfos: map[string]config.BidderInfo{"bidder1": infoKeyAPopulated},
 			expectedIFramesURLs: map[string]string{
-				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhostoverride.com%2Fa%2Fhost",
+				"bidder1": "https://bidder.com/iframe?redirect=http%3A%2F%2Fhostoverride.com%2Fbidder1%2Fhost",
 			},
 		},
 	}