Repository: prebid/prebid-server
Pull request #2114 (2021-12-19 19:58:16)

TheMediaGrid: Fix bug with wrong type in response
In case of multiple types, TheMediaGrid was sending the wrong type if the endpoint responded with a video type

mansinahar: @TheMediaGrid Can you please address @hhhjort's comment above when you get a chance? Thanks!

Patch:
diff --git a/adapters/adagio/adagio.go b/adapters/adagio/adagio.go
deleted file mode 100644
index 0da4d6ac..00000000
--- a/adapters/adagio/adagio.go
+++ /dev/null
@@ -1,139 +0,0 @@
-package adagio
-
-import (
-	"bytes"
-	"compress/gzip"
-	"encoding/json"
-	"fmt"
-	"github.com/mxmCherry/openrtb/v15/openrtb2"
-	"github.com/prebid/prebid-server/adapters"
-	"github.com/prebid/prebid-server/config"
-	"github.com/prebid/prebid-server/errortypes"
-	"github.com/prebid/prebid-server/openrtb_ext"
-	"net/http"
-)
-
-// Builder builds a new instance of the Adagio adapter for the given bidder with the given config.
-func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
-	bidder := &adapter{
-		endpoint: config.Endpoint,
-	}
-	return bidder, nil
-}
-
-type adapter struct {
-	endpoint string
-}
-
-type extBid struct {
-	Prebid *openrtb_ext.ExtBidPrebid
-}
-
-// MakeRequests prepares the HTTP requests which should be made to fetch bids.
-func (a *adapter) MakeRequests(request *openrtb2.BidRequest, _ *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
-	json, err := json.Marshal(request)
-	if err != nil {
-		return nil, []error{err}
-	}
-
-	headers := http.Header{}
-	headers.Add("Content-Type", "application/json;charset=utf-8")
-	headers.Add("Accept", "application/json")
-
-	if request.Device != nil {
-		if len(request.Device.IPv6) > 0 {
-			headers.Add("X-Forwarded-For", request.Device.IPv6)
-		}
-		if len(request.Device.IP) > 0 {
-			headers.Add("X-Forwarded-For", request.Device.IP)
-		}
-	}
-
-	if request.Test == 0 {
-		// Gzip the body
-		// Note: Gzipping could be handled natively later: https://github.com/prebid/prebid-server/issues/1812
-		var bodyBuf bytes.Buffer
-		gz := gzip.NewWriter(&bodyBuf)
-		if _, err = gz.Write(json); err == nil {
-			if err = gz.Close(); err == nil {
-				json = bodyBuf.Bytes()
-				headers.Add("Content-Encoding", "gzip")
-				// /!\ Go already sets the `Accept-Encoding: gzip` header. Never add it manually, or Go won't decompress the response.
-				//headers.Add("Accept-Encoding", "gzip")
-			}
-		}
-	}
-
-	requestToBidder := &adapters.RequestData{
-		Method:  "POST",
-		Uri:     a.endpoint,
-		Body:    json,
-		Headers: headers,
-	}
-
-	return []*adapters.RequestData{requestToBidder}, nil
-}
-
-const unexpectedStatusCodeFormat = "Unexpected status code: %d. Run with request.debug = 1 for more info"
-
-// MakeBids unpacks the server's response into Bids.
-func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, _ *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
-	switch response.StatusCode {
-	case http.StatusOK:
-		break
-	case http.StatusNoContent:
-		return nil, nil
-	case http.StatusServiceUnavailable:
-		fallthrough
-	case http.StatusBadRequest:
-		fallthrough
-	case http.StatusUnauthorized:
-		fallthrough
-	case http.StatusForbidden:
-		err := &errortypes.BadInput{
-			Message: fmt.Sprintf(unexpectedStatusCodeFormat, response.StatusCode),
-		}
-		return nil, []error{err}
-	default:
-		err := &errortypes.BadServerResponse{
-			Message: fmt.Sprintf(unexpectedStatusCodeFormat, response.StatusCode),
-		}
-		return nil, []error{err}
-	}
-
-	var openRTBBidderResponse openrtb2.BidResponse
-	if err := json.Unmarshal(response.Body, &openRTBBidderResponse); err != nil {
-		return nil, []error{err}
-	}
-
-	bidsCapacity := len(internalRequest.Imp)
-	errs := make([]error, 0, bidsCapacity)
-	bidderResponse := adapters.NewBidderResponseWithBidsCapacity(bidsCapacity)
-	var typedBid *adapters.TypedBid
-	for _, seatBid := range openRTBBidderResponse.SeatBid {
-		for _, bid := range seatBid.Bid {
-			activeBid := bid
-
-			activeExt := &extBid{}
-			if err := json.Unmarshal(activeBid.Ext, activeExt); err != nil {
-				errs = append(errs, err)
-			}
-
-			var bidType openrtb_ext.BidType
-			if activeExt.Prebid != nil && activeExt.Prebid.Type != "" {
-				bidType = activeExt.Prebid.Type
-			} else {
-				err := &errortypes.BadServerResponse{
-					Message: fmt.Sprintf("Failed to find native/banner/video mediaType \"%s\" ", activeBid.ImpID),
-				}
-				errs = append(errs, err)
-				continue
-			}
-
-			typedBid = &adapters.TypedBid{Bid: &activeBid, BidType: bidType}
-			bidderResponse.Bids = append(bidderResponse.Bids, typedBid)
-		}
-	}
-
-	return bidderResponse, nil
-}
diff --git a/adapters/algorix/algorix.go b/adapters/algorix/algorix.go
index 628207d6..d24521b4 100644
--- a/adapters/algorix/algorix.go
+++ b/adapters/algorix/algorix.go
@@ -19,6 +19,14 @@ type adapter struct {
 	EndpointTemplate *template.Template
 }
 
+type algorixVideoExt struct {
+	Rewarded int `json:"rewarded"`
+}
+
+type algorixResponseBidExt struct {
+	MediaType string `json:"mediaType"`
+}
+
 // Builder builds a new instance of the AlgoriX adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
 	endpoint, err := template.New("endpointTemplate").Parse(config.Endpoint)
@@ -121,6 +129,19 @@ func preProcess(request *openrtb2.BidRequest) {
 				request.Imp[i].Banner = &banner
 			}
 		}
+		if request.Imp[i].Video != nil {
+			var impExt adapters.ExtImpBidder
+			err := json.Unmarshal(request.Imp[i].Ext, &impExt)
+			if err != nil {
+				continue
+			}
+			if impExt.Prebid != nil && impExt.Prebid.IsRewardedInventory == 1 {
+				videoCopy := *request.Imp[i].Video
+				videoExt := algorixVideoExt{Rewarded: 1}
+				videoCopy.Ext, err = json.Marshal(&videoExt)
+				request.Imp[i].Video = &videoCopy
+			}
+		}
 	}
 }
 
@@ -147,32 +168,58 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest
 	}
 
 	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+	var errs []error
 
 	for _, seatBid := range bidResp.SeatBid {
 		for idx := range seatBid.Bid {
-			mediaType := getBidType(seatBid.Bid[idx].ImpID, internalRequest.Imp)
-			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
-				Bid:     &seatBid.Bid[idx],
-				BidType: mediaType,
-			})
+			mediaType, err := getBidType(seatBid.Bid[idx], internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+					Bid:     &seatBid.Bid[idx],
+					BidType: mediaType,
+				})
+			}
 		}
 	}
-	return bidResponse, nil
+
+	return bidResponse, errs
 }
 
-func getBidType(impId string, imps []openrtb2.Imp) openrtb_ext.BidType {
+func getBidType(bid openrtb2.Bid, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {
+	var bidExt algorixResponseBidExt
+	err := json.Unmarshal(bid.Ext, &bidExt)
+	if err == nil {
+		switch bidExt.MediaType {
+		case "banner":
+			return openrtb_ext.BidTypeBanner, nil
+		case "native":
+			return openrtb_ext.BidTypeNative, nil
+		case "video":
+			return openrtb_ext.BidTypeVideo, nil
+		}
+	}
+	var mediaType openrtb_ext.BidType
+	var typeCnt = 0
 	for _, imp := range imps {
-		if imp.ID == impId {
+		if imp.ID == bid.ImpID {
 			if imp.Banner != nil {
-				break
+				typeCnt += 1
+				mediaType = openrtb_ext.BidTypeBanner
 			}
 			if imp.Native != nil {
-				return openrtb_ext.BidTypeNative
+				typeCnt += 1
+				mediaType = openrtb_ext.BidTypeNative
 			}
 			if imp.Video != nil {
-				return openrtb_ext.BidTypeVideo
+				typeCnt += 1
+				mediaType = openrtb_ext.BidTypeVideo
 			}
 		}
 	}
-	return openrtb_ext.BidTypeBanner
+	if typeCnt == 1 {
+		return mediaType, nil
+	}
+	return mediaType, fmt.Errorf("unable to fetch mediaType in multi-format: %s", bid.ImpID)
 }
diff --git a/adapters/grid/grid.go b/adapters/grid/grid.go
index 850b21c5..6ebfb55e 100644
--- a/adapters/grid/grid.go
+++ b/adapters/grid/grid.go
@@ -19,6 +19,21 @@ type GridAdapter struct {
 	endpoint string
 }
 
+type GridBid struct {
+	*openrtb2.Bid
+	ContentType openrtb_ext.BidType `json:"content_type"`
+}
+
+type GridSeatBid struct {
+	*openrtb2.SeatBid
+	Bid []GridBid `json:"bid"`
+}
+
+type GridResponse struct {
+	*openrtb2.BidResponse
+	SeatBid []GridSeatBid `json:"seatbid,omitempty"`
+}
+
 type GridBidExt struct {
 	Bidder ExtBidder `json:"bidder"`
 }
@@ -329,7 +344,7 @@ func (a *GridAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReq
 		}}
 	}
 
-	var bidResp openrtb2.BidResponse
+	var bidResp GridResponse
 	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
 		return nil, []error{err}
 	}
@@ -339,13 +354,15 @@ func (a *GridAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReq
 	for _, sb := range bidResp.SeatBid {
 		for i := range sb.Bid {
 			bidMeta, err := getBidMeta(sb.Bid[i].Ext)
-			bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp)
+			bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp, sb.Bid[i])
 			if err != nil {
 				return nil, []error{err}
 			}
 
+			openrtb2Bid := sb.Bid[i].Bid
+
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
-				Bid:     &sb.Bid[i],
+				Bid:     openrtb2Bid,
 				BidType: bidType,
 				BidMeta: bidMeta,
 			})
@@ -378,19 +395,23 @@ func getBidMeta(ext json.RawMessage) (*openrtb_ext.ExtBidPrebidMeta, error) {
 	return bidMeta, nil
 }
 
-func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {
-	for _, imp := range imps {
-		if imp.ID == impID {
-			if imp.Banner != nil {
-				return openrtb_ext.BidTypeBanner, nil
-			}
+func getMediaTypeForImp(impID string, imps []openrtb2.Imp, bidWithType GridBid) (openrtb_ext.BidType, error) {
+	if bidWithType.ContentType != "" {
+		return bidWithType.ContentType, nil
+	} else {
+		for _, imp := range imps {
+			if imp.ID == impID {
+				if imp.Banner != nil {
+					return openrtb_ext.BidTypeBanner, nil
+				}
 
-			if imp.Video != nil {
-				return openrtb_ext.BidTypeVideo, nil
-			}
+				if imp.Video != nil {
+					return openrtb_ext.BidTypeVideo, nil
+				}
 
-			return "", &errortypes.BadServerResponse{
-				Message: fmt.Sprintf("Unknown impression type for ID: \"%s\"", impID),
+				return "", &errortypes.BadServerResponse{
+					Message: fmt.Sprintf("Unknown impression type for ID: \"%s\"", impID),
+				}
 			}
 		}
 	}
diff --git a/adapters/huaweiads/huaweiads.go b/adapters/huaweiads/huaweiads.go
index 39484422..f8acb2b9 100644
--- a/adapters/huaweiads/huaweiads.go
+++ b/adapters/huaweiads/huaweiads.go
@@ -30,6 +30,10 @@ const defaultUnknownNetworkType = 0
 const timeFormat = "2006-01-02 15:04:05.000"
 const defaultTimeZone = "+0200"
 const defaultModelName = "HUAWEI"
+const chineseSiteEndPoint = "https://acd.op.hicloud.com/ppsadx/getResult"
+const europeanSiteEndPoint = "https://adx-dre.op.hicloud.com/ppsadx/getResult"
+const asianSiteEndPoint = "https://adx-dra.op.hicloud.com/ppsadx/getResult"
+const russianSiteEndPoint = "https://adx-drru.op.hicloud.com/ppsadx/getResult"
 
 // creative type
 const (
@@ -228,7 +232,24 @@ type monitor struct {
 }
 
 type adapter struct {
-	endpoint string
+	endpoint  string
+	extraInfo ExtraInfo
+}
+
+type ExtraInfo struct {
+	PkgNameConvert              []pkgNameConvert `json:"pkgNameConvert,omitempty"`
+	CloseSiteSelectionByCountry string           `json:"closeSiteSelectionByCountry,omitempty"`
+}
+
+type pkgNameConvert struct {
+	ConvertedPkgName           string   `json:"convertedPkgName,omitempty"`
+	UnconvertedPkgNames        []string `json:"unconvertedPkgNames,omitempty"`
+	UnconvertedPkgNameKeyWords []string `json:"unconvertedPkgNameKeyWords,omitempty"`
+	UnconvertedPkgNamePrefixs  []string `json:"unconvertedPkgNamePrefixs,omitempty"`
+	ExceptionPkgNames          []string `json:"exceptionPkgNames,omitempty"`
+}
+
+type empty struct {
 }
 
 func (a *adapter) MakeRequests(openRTBRequest *openrtb2.BidRequest,
@@ -260,7 +281,8 @@ func (a *adapter) MakeRequests(openRTBRequest *openrtb2.BidRequest,
 	}
 	request.Multislot = multislot
 
-	if err := getHuaweiAdsReqJson(&request, openRTBRequest, huaweiAdsImpExt); err != nil {
+	countryCode, err := getHuaweiAdsReqJson(&request, openRTBRequest, huaweiAdsImpExt, a.extraInfo)
+	if err != nil {
 		return nil, []error{err}
 	}
 
@@ -278,7 +300,7 @@ func (a *adapter) MakeRequests(openRTBRequest *openrtb2.BidRequest,
 	header = getHeaders(huaweiAdsImpExt, openRTBRequest, isTestAuthorization)
 	bidRequest := &adapters.RequestData{
 		Method:  http.MethodPost,
-		Uri:     a.endpoint,
+		Uri:     getFinalEndPoint(countryCode, a.endpoint, a.extraInfo),
 		Body:    reqJSON,
 		Headers: header,
 	}
@@ -286,6 +308,37 @@ func (a *adapter) MakeRequests(openRTBRequest *openrtb2.BidRequest,
 	return []*adapters.RequestData{bidRequest}, nil
 }
 
+// countryCode is alpha2, choose the corresponding site end point
+func getFinalEndPoint(countryCode string, defaultEndpoint string, extraInfo ExtraInfo) string {
+	// closeSiteSelectionByCountry == 1, close site selection, use the defaultEndpoint
+	if "1" == extraInfo.CloseSiteSelectionByCountry {
+		return defaultEndpoint
+	}
+
+	if countryCode == "" || len(countryCode) > 2 {
+		return defaultEndpoint
+	}
+	var europeanSiteCountryCodeGroup = map[string]empty{"AX": {}, "AL": {}, "AD": {}, "AU": {}, "AT": {}, "BE": {},
+		"BA": {}, "BG": {}, "CA": {}, "HR": {}, "CY": {}, "CZ": {}, "DK": {}, "EE": {}, "FO": {}, "FI": {},
+		"FR": {}, "DE": {}, "GI": {}, "GR": {}, "GL": {}, "GG": {}, "VA": {}, "HU": {}, "IS": {}, "IE": {},
+		"IM": {}, "IL": {}, "IT": {}, "JE": {}, "YK": {}, "LV": {}, "LI": {}, "LT": {}, "LU": {}, "MT": {},
+		"MD": {}, "MC": {}, "ME": {}, "NL": {}, "AN": {}, "NZ": {}, "NO": {}, "PL": {}, "PT": {}, "RO": {},
+		"MF": {}, "VC": {}, "SM": {}, "RS": {}, "SX": {}, "SK": {}, "SI": {}, "ES": {}, "SE": {}, "CH": {},
+		"TR": {}, "UA": {}, "GB": {}, "US": {}, "MK": {}, "SJ": {}, "BQ": {}, "PM": {}, "CW": {}}
+	var russianSiteCountryCodeGroup = map[string]empty{"RU": {}}
+	var chineseSiteCountryCodeGroup = map[string]empty{"CN": {}}
+	// choose site
+	if _, exists := chineseSiteCountryCodeGroup[countryCode]; exists {
+		return chineseSiteEndPoint
+	} else if _, exists := russianSiteCountryCodeGroup[countryCode]; exists {
+		return russianSiteEndPoint
+	} else if _, exists := europeanSiteCountryCodeGroup[countryCode]; exists {
+		return europeanSiteEndPoint
+	} else {
+		return asianSiteEndPoint
+	}
+}
+
 func (a *adapter) MakeBids(openRTBRequest *openrtb2.BidRequest, requestToBidder *adapters.RequestData,
 	bidderRawResponse *adapters.ResponseData) (bidderResponse *adapters.BidderResponse, errs []error) {
 	httpStatusError := checkRespStatusCode(bidderRawResponse)
@@ -314,12 +367,52 @@ func (a *adapter) MakeBids(openRTBRequest *openrtb2.BidRequest, requestToBidder
 
 // Builder builds a new instance of the HuaweiAds adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	extraInfo, err := getExtraInfo(config.ExtraAdapterInfo)
+	if err != nil {
+		return nil, err
+	}
+
 	bidder := &adapter{
-		endpoint: config.Endpoint,
+		endpoint:  config.Endpoint,
+		extraInfo: extraInfo,
 	}
 	return bidder, nil
 }
 
+func getExtraInfo(v string) (ExtraInfo, error) {
+	var extraInfo ExtraInfo
+	if len(v) == 0 {
+		return extraInfo, nil
+	}
+
+	if err := json.Unmarshal([]byte(v), &extraInfo); err != nil {
+		return extraInfo, fmt.Errorf("invalid extra info: %v , pls check", err)
+	}
+
+	for _, convert := range extraInfo.PkgNameConvert {
+		if convert.ConvertedPkgName == "" {
+			return extraInfo, fmt.Errorf("invalid extra info: ConvertedPkgName is empty, pls check")
+		}
+
+		if convert.UnconvertedPkgNameKeyWords != nil {
+			for _, keyword := range convert.UnconvertedPkgNameKeyWords {
+				if keyword == "" {
+					return extraInfo, fmt.Errorf("invalid extra info: UnconvertedPkgNameKeyWords has a empty keyword, pls check")
+				}
+			}
+		}
+
+		if convert.UnconvertedPkgNamePrefixs != nil {
+			for _, prefix := range convert.UnconvertedPkgNamePrefixs {
+				if prefix == "" {
+					return extraInfo, fmt.Errorf("invalid extra info: UnconvertedPkgNamePrefixs has a empty value, pls check")
+				}
+			}
+		}
+	}
+	return extraInfo, nil
+}
+
 // getHeaders: get request header, Authorization -> digest
 func getHeaders(huaweiAdsImpExt *openrtb_ext.ExtImpHuaweiAds, request *openrtb2.BidRequest, isTestAuthorization bool) http.Header {
 	headers := http.Header{}
@@ -337,19 +430,19 @@ func getHeaders(huaweiAdsImpExt *openrtb_ext.ExtImpHuaweiAds, request *openrtb2.
 }
 
 // getHuaweiAdsReqJson: get body json for HuaweiAds request
-func getHuaweiAdsReqJson(request *huaweiAdsRequest, openRTBRequest *openrtb2.BidRequest, huaweiAdsImpExt *openrtb_ext.ExtImpHuaweiAds) error {
+func getHuaweiAdsReqJson(request *huaweiAdsRequest, openRTBRequest *openrtb2.BidRequest,
+	huaweiAdsImpExt *openrtb_ext.ExtImpHuaweiAds, extraInfo ExtraInfo) (countryCode string, err error) {
 	request.Version = huaweiAdxApiVersion
-	var err error
-	if err = getHuaweiAdsReqAppInfo(request, openRTBRequest); err != nil {
-		return err
+	if countryCode, err = getHuaweiAdsReqAppInfo(request, openRTBRequest, extraInfo); err != nil {
+		return "", err
 	}
 	if err = getHuaweiAdsReqDeviceInfo(request, openRTBRequest, huaweiAdsImpExt); err != nil {
-		return err
+		return "", err
 	}
 	getHuaweiAdsReqNetWorkInfo(request, openRTBRequest)
 	getHuaweiAdsReqRegsInfo(request, openRTBRequest)
 	getHuaweiAdsReqGeoInfo(request, openRTBRequest)
-	return nil
+	return countryCode, nil
 }
 
 func getHuaweiAdsReqAdslot30(huaweiAdsImpExt *openrtb_ext.ExtImpHuaweiAds,
@@ -459,7 +552,7 @@ func convertAdtypeString2Integer(adtypeLower string) int32 {
 }
 
 // getHuaweiAdsReqAppInfo: get app information for HuaweiAds request
-func getHuaweiAdsReqAppInfo(request *huaweiAdsRequest, openRTBRequest *openrtb2.BidRequest) error {
+func getHuaweiAdsReqAppInfo(request *huaweiAdsRequest, openRTBRequest *openrtb2.BidRequest, extraInfo ExtraInfo) (countryCode string, err error) {
 	var app app
 	if openRTBRequest.App != nil {
 		if openRTBRequest.App.Ver != "" {
@@ -471,9 +564,9 @@ func getHuaweiAdsReqAppInfo(request *huaweiAdsRequest, openRTBRequest *openrtb2.
 
 		// bundle cannot be empty, we need package name.
 		if openRTBRequest.App.Bundle != "" {
-			app.Pkgname = openRTBRequest.App.Bundle
+			app.Pkgname = getFinalPkgName(openRTBRequest.App.Bundle, extraInfo)
 		} else {
-			return errors.New("HuaweiAdsReqApp: Pkgname is empty.")
+			return "", errors.New("HuaweiAdsReqApp: Pkgname is empty.")
 		}
 
 		if openRTBRequest.App.Content != nil && openRTBRequest.App.Content.Language != "" {
@@ -482,9 +575,48 @@ func getHuaweiAdsReqAppInfo(request *huaweiAdsRequest, openRTBRequest *openrtb2.
 			app.Lang = "en"
 		}
 	}
-	app.Country = getCountryCode(openRTBRequest)
+	countryCode = getCountryCode(openRTBRequest)
+	app.Country = countryCode
 	request.App = app
-	return nil
+	return countryCode, nil
+}
+
+// when it has pkgNameConvert (include different rules)
+// 1. when bundleName in ExceptionPkgNames, finalPkgname = bundleName
+// 2. when bundleName conform UnconvertedPkgNames, finalPkgname = ConvertedPkgName
+// 3. when bundleName conform keyword, finalPkgname = ConvertedPkgName
+// 4. when bundleName conform prefix, finalPkgname = ConvertedPkgName
+func getFinalPkgName(bundleName string, extraInfo ExtraInfo) string {
+	for _, convert := range extraInfo.PkgNameConvert {
+		if convert.ConvertedPkgName == "" {
+			continue
+		}
+
+		for _, name := range convert.ExceptionPkgNames {
+			if name == bundleName {
+				return bundleName
+			}
+		}
+
+		for _, name := range convert.UnconvertedPkgNames {
+			if name == bundleName || name == "*" {
+				return convert.ConvertedPkgName
+			}
+		}
+
+		for _, keyword := range convert.UnconvertedPkgNameKeyWords {
+			if strings.Index(bundleName, keyword) > 0 {
+				return convert.ConvertedPkgName
+			}
+		}
+
+		for _, prefix := range convert.UnconvertedPkgNamePrefixs {
+			if strings.HasPrefix(bundleName, prefix) {
+				return convert.ConvertedPkgName
+			}
+		}
+	}
+	return bundleName
 }
 
 // getClientTime: get field clientTime, format: 2006-01-02 15:04:05.000+0200
@@ -552,7 +684,12 @@ func convertCountryCode(country string) (out string) {
 	if country == "" {
 		return defaultCountryName
 	}
-	var mapCountryCodeAlpha3ToAlpha2 = map[string]string{"CHL": "CL", "CHN": "CN", "ARE": "AE"}
+	var mapCountryCodeAlpha3ToAlpha2 = map[string]string{"AND": "AD", "AGO": "AO", "AUT": "AT", "BGD": "BD",
+		"BLR": "BY", "CAF": "CF", "TCD": "TD", "CHL": "CL", "CHN": "CN", "COG": "CG", "COD": "CD", "DNK": "DK",
+		"GNQ": "GQ", "EST": "EE", "GIN": "GN", "GNB": "GW", "GUY": "GY", "IRQ": "IQ", "IRL": "IE", "ISR": "IL",
+		"KAZ": "KZ", "LBY": "LY", "MDG": "MG", "MDV": "MV", "MEX": "MX", "MNE": "ME", "MOZ": "MZ", "PAK": "PK",
+		"PNG": "PG", "PRY": "PY", "POL": "PL", "PRT": "PT", "SRB": "RS", "SVK": "SK", "SVN": "SI", "SWE": "SE",
+		"TUN": "TN", "TUR": "TR", "TKM": "TM", "UKR": "UA", "ARE": "AE", "URY": "UY"}
 	if mappedCountry, exists := mapCountryCodeAlpha3ToAlpha2[country]; exists {
 		return mappedCountry
 	}
diff --git a/adapters/vidoomy/vidoomy.go b/adapters/vidoomy/vidoomy.go
new file mode 100644
index 00000000..57fbb09d
--- /dev/null
+++ b/adapters/vidoomy/vidoomy.go
@@ -0,0 +1,173 @@
+package vidoomy
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/mxmCherry/openrtb/v15/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"net/http"
+)
+
+type adapter struct {
+	endpoint string
+}
+
+func (a adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var errors []error
+
+	reqs := make([]*adapters.RequestData, 0, len(request.Imp))
+
+	header := getHeaders(request)
+	for _, imp := range request.Imp {
+
+		// Split up multi-impression requests into multiple requests so that
+		// each split request is only associated to a single impression
+		reqCopy := *request
+		reqCopy.Imp = []openrtb2.Imp{imp}
+
+		if err := changeRequestForBidService(&reqCopy); err != nil {
+			errors = append(errors, err)
+			continue
+		}
+
+		reqJSON, err := json.Marshal(&reqCopy)
+		if err != nil {
+			errors = append(errors, err)
+			continue
+		}
+
+		reqs = append(reqs, &adapters.RequestData{
+			Method:  "POST",
+			Uri:     a.endpoint,
+			Body:    reqJSON,
+			Headers: header,
+		})
+	}
+
+	return reqs, errors
+}
+
+func getHeaders(request *openrtb2.BidRequest) http.Header {
+	headers := http.Header{}
+
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("x-openrtb-version", "2.5")
+
+	if request.Device == nil {
+		return headers
+	}
+
+	if request.Device.UA != "" {
+		headers.Set("User-Agent", request.Device.UA)
+	}
+
+	if len(request.Device.IPv6) > 0 {
+		headers.Add("X-Forwarded-For", request.Device.IPv6)
+	}
+
+	if len(request.Device.IP) > 0 {
+		headers.Add("X-Forwarded-For", request.Device.IP)
+	}
+
+	return headers
+}
+
+func changeRequestForBidService(request *openrtb2.BidRequest) error {
+	if request.Imp[0].Banner == nil {
+		return nil
+	}
+
+	banner := *request.Imp[0].Banner
+	request.Imp[0].Banner = &banner
+
+	if banner.W != nil && banner.H != nil {
+		if *banner.W == 0 || *banner.H == 0 {
+			return fmt.Errorf("invalid sizes provided for Banner %d x %d", *banner.W, *banner.H)
+		}
+		return nil
+	}
+
+	if len(banner.Format) == 0 {
+		return fmt.Errorf("no sizes provided for Banner %v", banner.Format)
+	}
+
+	banner.W = openrtb2.Int64Ptr(banner.Format[0].W)
+	banner.H = openrtb2.Int64Ptr(banner.Format[0].H)
+
+	return nil
+}
+
+func (a 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.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d.", 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(internalRequest.Imp))
+
+	for _, sb := range bidResp.SeatBid {
+		for _, bid := range sb.Bid {
+			bid := bid
+			exists, mediaType := getImpInfo(bid.ImpID, internalRequest.Imp)
+			if !exists {
+				return nil, []error{&errortypes.BadServerResponse{
+					Message: fmt.Sprintf("Unknown ad unit code '%s'", bid.ImpID),
+				}}
+			}
+
+			if openrtb_ext.BidTypeBanner != mediaType &&
+				openrtb_ext.BidTypeVideo != mediaType {
+				//only banner and video are supported, anything else is ignored
+				continue
+			}
+
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+				Bid:     &bid,
+				BidType: mediaType,
+			})
+		}
+	}
+
+	return bidResponse, nil
+}
+
+func getImpInfo(impId string, imps []openrtb2.Imp) (bool, openrtb_ext.BidType) {
+	var mediaType openrtb_ext.BidType
+	for _, imp := range imps {
+		if imp.ID == impId {
+
+			if imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			} else if imp.Banner != nil {
+				mediaType = openrtb_ext.BidTypeBanner
+			}
+
+			return true, mediaType
+		}
+	}
+	return false, mediaType
+}
+
+// Builder builds a new instance of the Vidoomy adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
diff --git a/config/config.go b/config/config.go
index a2413ffe..e7a9effa 100644
--- a/config/config.go
+++ b/config/config.go
@@ -807,7 +807,6 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.33across.partner_id", "")
 	v.SetDefault("adapters.aceex.endpoint", "http://bl-us.aceex.io/?uqhash={{.AccountID}}")
 	v.SetDefault("adapters.acuityads.endpoint", "http://{{.Host}}.admanmedia.com/bid?token={{.AccountID}}")
-	v.SetDefault("adapters.adagio.endpoint", "https://mp.4dex.io/ortb2")
 	v.SetDefault("adapters.adf.endpoint", "https://adx.adform.net/adx/openrtb")
 	v.SetDefault("adapters.adform.endpoint", "https://adx.adform.net/adx/openrtb")
 	v.SetDefault("adapters.adgeneration.endpoint", "https://d.socdm.com/adsv/v1")
@@ -943,6 +942,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.valueimpression.endpoint", "http://useast.quantumdex.io/auction/pbs")
 	v.SetDefault("adapters.verizonmedia.disabled", true)
 	v.SetDefault("adapters.videobyte.endpoint", "https://x.videobyte.com/ortbhb")
+	v.SetDefault("adapters.vidoomy.endpoint", "https://p.vidoomy.com/api/rtbserver/pbs")
 	v.SetDefault("adapters.viewdeos.endpoint", "http://ghb.sync.viewdeos.com/pbs/ortb")
 	v.SetDefault("adapters.visx.endpoint", "https://t.visx.net/s2s_bid?wrapperType=s2s_prebid_standard:0.1.0")
 	v.SetDefault("adapters.vrtcal.endpoint", "http://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804")
diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go
index 38b27970..452e7ed5 100644
--- a/endpoints/openrtb2/amp_auction.go
+++ b/endpoints/openrtb2/amp_auction.go
@@ -26,6 +26,7 @@ import (
 	"github.com/prebid/prebid-server/stored_requests/backends/empty_fetcher"
 	"github.com/prebid/prebid-server/usersync"
 	"github.com/prebid/prebid-server/util/iputil"
+	"github.com/prebid/prebid-server/version"
 
 	"github.com/buger/jsonparser"
 	"github.com/golang/glog"
@@ -133,6 +134,7 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
 	// and "Access-Control-Allow-Credentials" are handled in CORS middleware
 	w.Header().Set("AMP-Access-Control-Allow-Source-Origin", origin)
 	w.Header().Set("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin")
+	w.Header().Set("X-Prebid", version.BuildXPrebidHeader(version.Ver))
 
 	req, errL := deps.parseAmpRequest(r)
 	ao.Errors = append(ao.Errors, errL...)
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 4d68db50..3f0a35e8 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"github.com/prebid/prebid-server/firstpartydata"
+	"github.com/prebid/prebid-server/version"
 
 	"github.com/buger/jsonparser"
 	jsonpatch "github.com/evanphx/json-patch"
@@ -148,6 +149,8 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
 		deps.analytics.LogAuctionObject(&ao)
 	}()
 
+	w.Header().Set("X-Prebid", version.BuildXPrebidHeader(version.Ver))
+
 	req, impExtInfoMap, errL := deps.parseRequest(r)
 	if errortypes.ContainsFatalError(errL) && writeError(errL, w, &labels) {
 		return
@@ -234,7 +237,6 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
 	enc := json.NewEncoder(w)
 	enc.SetEscapeHTML(false)
 
-	// Fixes #328
 	w.Header().Set("Content-Type", "application/json")
 
 	// If an error happens when encoding the response, there isn't much we can do.
diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go
index cbffe2e3..1f16f92a 100644
--- a/endpoints/openrtb2/video_auction.go
+++ b/endpoints/openrtb2/video_auction.go
@@ -22,6 +22,7 @@ import (
 	"github.com/prebid/prebid-server/errortypes"
 	"github.com/prebid/prebid-server/util/iputil"
 	"github.com/prebid/prebid-server/util/uuidutil"
+	"github.com/prebid/prebid-server/version"
 
 	"github.com/golang/glog"
 	"github.com/julienschmidt/httprouter"
@@ -153,6 +154,8 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
 		deps.analytics.LogVideoObject(&vo)
 	}()
 
+	w.Header().Set("X-Prebid", version.BuildXPrebidHeader(version.Ver))
+
 	lr := &io.LimitedReader{
 		R: r.Body,
 		N: deps.cfg.MaxRequestSize,
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 8075b7f1..850b41ab 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -5,7 +5,6 @@ import (
 	"github.com/prebid/prebid-server/adapters/33across"
 	"github.com/prebid/prebid-server/adapters/aceex"
 	"github.com/prebid/prebid-server/adapters/acuityads"
-	"github.com/prebid/prebid-server/adapters/adagio"
 	"github.com/prebid/prebid-server/adapters/adf"
 	"github.com/prebid/prebid-server/adapters/adgeneration"
 	"github.com/prebid/prebid-server/adapters/adhese"
@@ -125,6 +124,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/unicorn"
 	"github.com/prebid/prebid-server/adapters/unruly"
 	"github.com/prebid/prebid-server/adapters/videobyte"
+	"github.com/prebid/prebid-server/adapters/vidoomy"
 	"github.com/prebid/prebid-server/adapters/visx"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
 	"github.com/prebid/prebid-server/adapters/yahoossp"
@@ -144,7 +144,6 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.Bidder33Across:          ttx.Builder,
 		openrtb_ext.BidderAceex:             aceex.Builder,
 		openrtb_ext.BidderAcuityAds:         acuityads.Builder,
-		openrtb_ext.BidderAdagio:            adagio.Builder,
 		openrtb_ext.BidderAdf:               adf.Builder,
 		openrtb_ext.BidderAdform:            adf.Builder,
 		openrtb_ext.BidderAdgeneration:      adgeneration.Builder,
@@ -272,6 +271,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderValueImpression:   apacdex.Builder,
 		openrtb_ext.BidderVerizonMedia:      yahoossp.Builder,
 		openrtb_ext.BidderVideoByte:         videobyte.Builder,
+		openrtb_ext.BidderVidoomy:           vidoomy.Builder,
 		openrtb_ext.BidderViewdeos:          adtelligent.Builder,
 		openrtb_ext.BidderVisx:              visx.Builder,
 		openrtb_ext.BidderVrtcal:            vrtcal.Builder,
diff --git a/exchange/adapter_util.go b/exchange/adapter_util.go
index 9ab27561..50308dae 100644
--- a/exchange/adapter_util.go
+++ b/exchange/adapter_util.go
@@ -79,6 +79,7 @@ func GetActiveBidders(infos config.BidderInfos) map[string]openrtb_ext.BidderNam
 func GetDisabledBiddersErrorMessages(infos config.BidderInfos) map[string]string {
 	disabledBidders := map[string]string{
 		"lifestreet": `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
+		"adagio":     `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 	}
 
 	for name, info := range infos {
diff --git a/exchange/bidder.go b/exchange/bidder.go
index 2aae63e2..40e78e83 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -140,7 +140,7 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, request *openrtb2.B
 		}
 		return nil, errs
 	}
-	xPrebidHeader := buildXPrebidHeader(request, version.Ver)
+	xPrebidHeader := version.BuildXPrebidHeaderForRequest(request, version.Ver)
 
 	for i := 0; i < len(reqData); i++ {
 		if reqData[i].Headers != nil {
diff --git a/exchange/utils.go b/exchange/utils.go
index ec5b666d..44737af3 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -5,7 +5,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"math/rand"
-	"strings"
 
 	"github.com/mxmCherry/openrtb/v15/openrtb2"
 	"github.com/prebid/go-gdpr/vendorconsent"
@@ -713,42 +712,6 @@ func getExtBidAdjustmentFactors(requestExt *openrtb_ext.ExtRequest) map[string]f
 	return bidAdjustmentFactors
 }
 
-func buildXPrebidHeader(bidRequest *openrtb2.BidRequest, version string) string {
-	req := &openrtb_ext.RequestWrapper{BidRequest: bidRequest}
-
-	sb := &strings.Builder{}
-	writeNameVersionRecord(sb, "pbs-go", version)
-
-	if reqExt, err := req.GetRequestExt(); err == nil && reqExt != nil {
-		if prebidExt := reqExt.GetPrebid(); prebidExt != nil {
-			if channel := prebidExt.Channel; channel != nil {
-				writeNameVersionRecord(sb, channel.Name, channel.Version)
-			}
-		}
-	}
-	if appExt, err := req.GetAppExt(); err == nil && appExt != nil {
-		if prebidExt := appExt.GetPrebid(); prebidExt != nil {
-			writeNameVersionRecord(sb, prebidExt.Source, prebidExt.Version)
-		}
-	}
-	return sb.String()
-}
-
-func writeNameVersionRecord(sb *strings.Builder, name, version string) {
-	if name == "" {
-		return
-	}
-	if version == "" {
-		version = "unknown"
-	}
-	if sb.Len() != 0 {
-		sb.WriteString(",")
-	}
-	sb.WriteString(name)
-	sb.WriteString("/")
-	sb.WriteString(version)
-}
-
 func applyFPD(fpd *firstpartydata.ResolvedFirstPartyData, bidReq *openrtb2.BidRequest) {
 	if fpd.Site != nil {
 		bidReq.Site = fpd.Site
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 941f1a56..7cb7a07b 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -79,7 +79,6 @@ const (
 	Bidder33Across          BidderName = "33across"
 	BidderAceex             BidderName = "aceex"
 	BidderAcuityAds         BidderName = "acuityads"
-	BidderAdagio            BidderName = "adagio"
 	BidderAdf               BidderName = "adf"
 	BidderAdform            BidderName = "adform"
 	BidderAdgeneration      BidderName = "adgeneration"
@@ -207,6 +206,7 @@ const (
 	BidderValueImpression   BidderName = "valueimpression"
 	BidderVerizonMedia      BidderName = "verizonmedia"
 	BidderVideoByte         BidderName = "videobyte"
+	BidderVidoomy           BidderName = "vidoomy"
 	BidderVisx              BidderName = "visx"
 	BidderViewdeos          BidderName = "viewdeos"
 	BidderVrtcal            BidderName = "vrtcal"
@@ -225,7 +225,6 @@ func CoreBidderNames() []BidderName {
 		Bidder33Across,
 		BidderAceex,
 		BidderAcuityAds,
-		BidderAdagio,
 		BidderAdf,
 		BidderAdform,
 		BidderAdgeneration,
@@ -353,6 +352,7 @@ func CoreBidderNames() []BidderName {
 		BidderValueImpression,
 		BidderVerizonMedia,
 		BidderVideoByte,
+		BidderVidoomy,
 		BidderViewdeos,
 		BidderVisx,
 		BidderVrtcal,
diff --git a/openrtb_ext/imp_vidoomy.go b/openrtb_ext/imp_vidoomy.go
new file mode 100644
index 00000000..21072dae
--- /dev/null
+++ b/openrtb_ext/imp_vidoomy.go
@@ -0,0 +1,5 @@
+package openrtb_ext
+
+type ImpExtVidoomy struct {
+	ZoneID string `json:"zoneId"`
+}
diff --git a/static/bidder-info/adagio.yaml b/static/bidder-info/adagio.yaml
deleted file mode 100644
index 891b2a6c..00000000
--- a/static/bidder-info/adagio.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-maintainer:
-  email: "dev@adagio.io"
-gvlVendorID: 617
-modifyingVastXmlAllowed: false
-debug:
-  allow: true
-capabilities:
-  site:
-    mediaTypes:
-      - banner
-      - video
-      - native
-userSync:
-  redirect:
-    url: "https://mp.4dex.io/sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}"
-    userMacro: "{{UID}}"
diff --git a/static/bidder-info/vidoomy.yaml b/static/bidder-info/vidoomy.yaml
new file mode 100644
index 00000000..1cd683a7
--- /dev/null
+++ b/static/bidder-info/vidoomy.yaml
@@ -0,0 +1,16 @@
+maintainer:
+  email: support@vidoomy.com
+gvlVendorID: 380
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+  app:
+    mediaTypes:
+      - banner
+      - video
+userSync:
+    iframe:
+      url: "https://vid.vidoomy.com/sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}"
+      userMacro: "{{VID}}"
\ No newline at end of file
diff --git a/static/bidder-params/adagio.json b/static/bidder-params/adagio.json
deleted file mode 100644
index 955c58c7..00000000
--- a/static/bidder-params/adagio.json
+++ /dev/null
@@ -1,94 +0,0 @@
-{
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "title": "Adagio Adapter Params",
-  "description": "A schema which validates params accepted by the Adagio adapter",
-  "type": "object",
-  "required": [
-    "organizationId",
-    "site",
-    "placement"
-  ],
-  "properties": {
-    "organizationId": {
-      "type": "string",
-      "description": "Name to identify the organization",
-      "minLength": 1
-    },
-    "site": {
-      "type": "string",
-      "description": "Name to identify the site",
-      "minLength": 1
-    },
-    "placement": {
-      "type": "string",
-      "description": "Name to identify the placement",
-      "minLength": 1
-    },
-    "pageviewId": {
-      "type": "string",
-      "description": "Name to identify the pageview"
-    },
-    "pagetype": {
-      "type": "string",
-      "description": "Name to identify the page type"
-    },
-    "category": {
-      "type": "string",
-      "description": "Name to identify the category"
-    },
-    "subcategory": {
-      "type": "string",
-      "description": "Name to identify the subcategory"
-    },
-    "environment": {
-      "type": "string",
-      "description": "Name to identify the environment"
-    },
-    "features": {
-      "type": "object",
-      "patternProperties": {
-        "^[a-zA-Z_]": { "type": "string" }
-      }
-    },
-    "prebidVersion:": {
-      "type": "string",
-      "description": "Name to identify the version of Prebid.js"
-    },
-    "debug": {
-      "type": "object",
-      "properties": {
-        "enabled": {
-          "type": "boolean"
-        },
-        "cpm": {
-          "type": "number"
-        },
-        "lazyLoad": {
-          "type": "object",
-          "properties": {
-            "enabled": {
-              "type": "boolean"
-            },
-            "threshold": {
-              "type": "number"
-            },
-            "rootMargin":  {
-              "type": "string"
-            }
-          }
-        }
-      }
-    },
-    "native": {
-      "type": "object",
-      "properties": {
-        "context": {
-          "type": "number"
-        },
-        "plcmttype": {
-          "type": "number"
-        }
-      }
-    }
-  }
-}
diff --git a/static/bidder-params/vidoomy.json b/static/bidder-params/vidoomy.json
new file mode 100644
index 00000000..9c49daf7
--- /dev/null
+++ b/static/bidder-params/vidoomy.json
@@ -0,0 +1,14 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Vidoomy Adapter Params",
+  "description": "A schema which validates params accepted by the Vidoomy adapter",
+  "type": "object",
+  "properties": {
+    "zoneId": {
+      "type": "string",
+      "description": "Specific zone ID for this placement, belonging to app/site",
+      "minLength": 1
+    }
+  },
+  "required": ["zoneId"]
+}
\ No newline at end of file
diff --git a/version/version.go b/version/version.go
index e9310276..4292abbe 100644
--- a/version/version.go
+++ b/version/version.go
@@ -6,6 +6,9 @@ package version
 // Populated automatically at build / releases in the Docker image
 var Ver string
 
+// VerUnknown is the version used if Ver has not been set by ldflags.
+const VerUnknown = "unknown"
+
 // Rev holds binary revision string
 // Populated using:
 //    go build -ldflags "-X github.com/prebid/prebid-server/version.Rev=`git rev-parse --short HEAD`"
diff --git a/version/xprebidheader.go b/version/xprebidheader.go
new file mode 100644
index 00000000..5d91ca49
--- /dev/null
+++ b/version/xprebidheader.go
@@ -0,0 +1,53 @@
+package version
+
+import (
+	"strings"
+
+	"github.com/mxmCherry/openrtb/v15/openrtb2"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+const xPrebidHeaderVersionPrefix = "pbs-go"
+
+func BuildXPrebidHeader(version string) string {
+	sb := &strings.Builder{}
+	writeNameVersionRecord(sb, xPrebidHeaderVersionPrefix, version)
+	return sb.String()
+}
+
+func BuildXPrebidHeaderForRequest(bidRequest *openrtb2.BidRequest, version string) string {
+	req := &openrtb_ext.RequestWrapper{BidRequest: bidRequest}
+
+	sb := &strings.Builder{}
+	writeNameVersionRecord(sb, xPrebidHeaderVersionPrefix, version)
+
+	if reqExt, err := req.GetRequestExt(); err == nil && reqExt != nil {
+		if prebidExt := reqExt.GetPrebid(); prebidExt != nil {
+			if channel := prebidExt.Channel; channel != nil {
+				writeNameVersionRecord(sb, channel.Name, channel.Version)
+			}
+		}
+	}
+	if appExt, err := req.GetAppExt(); err == nil && appExt != nil {
+		if prebidExt := appExt.GetPrebid(); prebidExt != nil {
+			writeNameVersionRecord(sb, prebidExt.Source, prebidExt.Version)
+		}
+	}
+	return sb.String()
+}
+
+func writeNameVersionRecord(sb *strings.Builder, name, version string) {
+	if name == "" {
+		return
+	}
+	if version == "" {
+		version = VerUnknown
+	}
+	if sb.Len() != 0 {
+		sb.WriteString(",")
+	}
+	sb.WriteString(name)
+	sb.WriteString("/")
+	sb.WriteString(version)
+}


Test patch:
diff --git a/adapters/adagio/adagio_test.go b/adapters/adagio/adagio_test.go
deleted file mode 100644
index d5e25c78..00000000
--- a/adapters/adagio/adagio_test.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package adagio
-
-import (
-	"encoding/json"
-	"github.com/mxmCherry/openrtb/v15/openrtb2"
-	"github.com/stretchr/testify/assert"
-	"testing"
-
-	"github.com/prebid/prebid-server/adapters/adapterstest"
-	"github.com/prebid/prebid-server/config"
-	"github.com/prebid/prebid-server/openrtb_ext"
-)
-
-func buildFakeBidRequest() openrtb2.BidRequest {
-	imp1 := openrtb2.Imp{
-		ID:     "some-impression-id",
-		Banner: &openrtb2.Banner{},
-		Ext:    json.RawMessage(`{"bidder": {"organizationId": "1000", "site": "site-name", "placement": "ban_atf"}}`),
-	}
-
-	fakeBidRequest := openrtb2.BidRequest{
-		ID:  "some-request-id",
-		Imp: []openrtb2.Imp{imp1},
-	}
-
-	return fakeBidRequest
-}
-
-func TestJsonSamples(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderAdagio, config.Adapter{
-		Endpoint: "http://localhost/prebid_server"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	adapterstest.RunJSONBidderTest(t, "adagiotest", bidder)
-}
-
-func TestMakeRequests_NoGzip(t *testing.T) {
-	fakeBidRequest := buildFakeBidRequest()
-	fakeBidRequest.Test = 1 // Do not use Gzip in Test Mode.
-
-	bidder, buildErr := Builder(openrtb_ext.BidderAdagio, config.Adapter{
-		Endpoint: "http://localhost/prebid_server"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	requestData, errs := bidder.MakeRequests(&fakeBidRequest, nil)
-
-	assert.Nil(t, errs)
-	assert.Equal(t, 1, len(requestData))
-
-	body := &openrtb2.BidRequest{}
-	err := json.Unmarshal(requestData[0].Body, body)
-	assert.NoError(t, err, "Request body unmarshalling error should be nil")
-	assert.Equal(t, 1, len(body.Imp))
-}
-
-func TestMakeRequests_Gzip(t *testing.T) {
-	fakeBidRequest := buildFakeBidRequest()
-
-	bidder, buildErr := Builder(openrtb_ext.BidderAdagio, config.Adapter{
-		Endpoint: "http://localhost/prebid_server"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	requestData, errs := bidder.MakeRequests(&fakeBidRequest, nil)
-	assert.Empty(t, errs, "Got errors while making requests")
-	assert.Equal(t, []string{"gzip"}, requestData[0].Headers["Content-Encoding"])
-}
diff --git a/adapters/adagio/adagiotest/exemplary/banner-web.json b/adapters/adagio/adagiotest/exemplary/banner-web.json
deleted file mode 100644
index 732b40d2..00000000
--- a/adapters/adagio/adagiotest/exemplary/banner-web.json
+++ /dev/null
@@ -1,155 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "device": {
-      "ua": "test-user-agent",
-      "ip": "123.123.123.123",
-      "language": "en",
-      "dnt": 0
-    },
-    "tmax": 1000,
-    "user": {
-      "buyeruid": "awesome-user"
-    },
-    "site": {
-      "page": "test.com",
-      "publisher": {
-        "id": "123456789"
-      }
-    },
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w":320,
-          "h":50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ],
-          "X-Forwarded-For": [
-            "123.123.123.123"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "device": {
-            "ua": "test-user-agent",
-            "ip": "123.123.123.123",
-            "language": "en",
-            "dnt": 0
-          },
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w":320,
-                "h":50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ],
-          "site": {
-            "page": "test.com",
-            "publisher": {
-              "id": "123456789"
-            }
-          },
-          "user": {
-            "buyeruid": "awesome-user"
-          },
-          "tmax": 1000
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "awesome-resp-id",
-          "seatbid": [
-            {
-              "bid": [
-                {
-                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-                  "impid": "some-impression-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "w": 320,
-                  "h": 50,
-                  "ext": {
-                    "prebid": {
-                      "type": "banner"
-                    }
-                  }
-                }
-              ],
-              "seat": "adagio"
-            }
-          ],
-          "cur": "USD",
-          "ext": {
-            "responsetimemillis": {
-              "adagio": 154
-            },
-            "tmaxrequest": 1000
-          }
-        }
-      }
-    }
-  ],
-  "expectedBidResponses": [
-    {
-      "bids":[
-        {
-          "bid":  {
-            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-            "impid": "some-impression-id",
-            "price": 3.5,
-            "adm": "awesome-markup",
-            "crid": "20",
-            "adomain": [
-              "awesome.com"
-            ],
-            "w": 320,
-            "h": 50,
-            "ext": {
-              "prebid": {
-                "type": "banner"
-              }
-            }
-          },
-          "type": "banner"
-        }
-      ]
-    }
-  ]
-}
diff --git a/adapters/adagio/adagiotest/exemplary/multi-format.json b/adapters/adagio/adagiotest/exemplary/multi-format.json
deleted file mode 100644
index 85e0be26..00000000
--- a/adapters/adagio/adagiotest/exemplary/multi-format.json
+++ /dev/null
@@ -1,165 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "device": {
-      "ua": "test-user-agent",
-      "ip": "123.123.123.123",
-      "language": "en",
-      "dnt": 0
-    },
-    "tmax": 1000,
-    "user": {
-      "buyeruid": "awesome-user"
-    },
-    "site": {
-      "page": "test.com",
-      "publisher": {
-        "id": "123456789"
-      }
-    },
-    "imp": [
-      {
-        "id": "multi-format-id",
-        "banner": {
-          "w":320,
-          "h":50
-        },
-        "video": {
-          "mimes": ["video\/mp4"],
-          "w": 640,
-          "h": 480
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ],
-          "X-Forwarded-For": [
-            "123.123.123.123"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "device": {
-            "ua": "test-user-agent",
-            "ip": "123.123.123.123",
-            "language": "en",
-            "dnt": 0
-          },
-          "imp": [
-            {
-              "id": "multi-format-id",
-              "banner": {
-                "w":320,
-                "h":50
-              },
-              "video": {
-                "mimes": ["video\/mp4"],
-                "w": 640,
-                "h": 480
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ],
-          "site": {
-            "page": "test.com",
-            "publisher": {
-              "id": "123456789"
-            }
-          },
-          "user": {
-            "buyeruid": "awesome-user"
-          },
-          "tmax": 1000
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "awesome-resp-id",
-          "seatbid": [
-            {
-              "bid": [
-                {
-                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-                  "impid": "multi-format-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "w": 320,
-                  "h": 50,
-                  "ext": {
-                    "prebid": {
-                      "type": "banner"
-                    }
-                  }
-                }
-              ],
-              "seat": "adagio"
-            }
-          ],
-          "cur": "USD",
-          "ext": {
-            "responsetimemillis": {
-              "adagio": 154
-            },
-            "tmaxrequest": 1000
-          }
-        }
-      }
-    }
-  ],
-  "expectedBidResponses": [
-    {
-      "bids":[
-        {
-          "bid":  {
-            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-            "impid": "multi-format-id",
-            "price": 3.5,
-            "adm": "awesome-markup",
-            "crid": "20",
-            "adomain": [
-              "awesome.com"
-            ],
-            "w": 320,
-            "h": 50,
-            "ext": {
-              "prebid": {
-                "type": "banner"
-              }
-            }
-          },
-          "type": "banner"
-        }
-      ]
-    }
-  ]
-}
diff --git a/adapters/adagio/adagiotest/exemplary/multi-imp.json b/adapters/adagio/adagiotest/exemplary/multi-imp.json
deleted file mode 100644
index 66af28ea..00000000
--- a/adapters/adagio/adagiotest/exemplary/multi-imp.json
+++ /dev/null
@@ -1,222 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "device": {
-      "ua": "test-user-agent",
-      "ip": "123.123.123.123",
-      "language": "en",
-      "dnt": 0
-    },
-    "tmax": 1000,
-    "user": {
-      "buyeruid": "awesome-user"
-    },
-    "site": {
-      "page": "test.com",
-      "publisher": {
-        "id": "123456789"
-      }
-    },
-    "imp": [
-      {
-        "id": "banner-impression-id",
-        "banner": {
-          "w":320,
-          "h":50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      },
-      {
-        "id": "video-impression-id",
-        "video": {
-          "mimes": ["video\/mp4"],
-          "w": 640,
-          "h": 480
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "in_article"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ],
-          "X-Forwarded-For": [
-            "123.123.123.123"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "device": {
-            "ua": "test-user-agent",
-            "ip": "123.123.123.123",
-            "language": "en",
-            "dnt": 0
-          },
-          "imp": [
-            {
-              "id": "banner-impression-id",
-              "banner": {
-                "w":320,
-                "h":50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            },
-            {
-              "id": "video-impression-id",
-              "video": {
-                "mimes": ["video\/mp4"],
-                "w": 640,
-                "h": 480
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "in_article"
-                }
-              }
-            }
-          ],
-          "site": {
-            "page": "test.com",
-            "publisher": {
-              "id": "123456789"
-            }
-          },
-          "user": {
-            "buyeruid": "awesome-user"
-          },
-          "tmax": 1000
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "awesome-resp-id",
-          "seatbid": [
-            {
-              "bid": [
-                {
-                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-                  "impid": "banner-impression-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "w": 320,
-                  "h": 50,
-                  "ext": {
-                    "prebid": {
-                      "type": "banner"
-                    }
-                  }
-                },
-                {
-                  "id": "b4ae1b4e2fc24a4fb45540082e98e162",
-                  "impid": "video-impression-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "w": 640,
-                  "h": 480,
-                  "ext": {
-                    "prebid": {
-                      "type": "video"
-                    }
-                  }
-                }
-              ],
-              "seat": "adagio"
-            }
-          ],
-          "cur": "USD",
-          "ext": {
-            "responsetimemillis": {
-              "adagio": 154
-            },
-            "tmaxrequest": 1000
-          }
-        }
-      }
-    }
-  ],
-  "expectedBidResponses": [
-    {
-      "bids":[
-        {
-          "bid":  {
-            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-            "impid": "banner-impression-id",
-            "price": 3.5,
-            "adm": "awesome-markup",
-            "crid": "20",
-            "adomain": [
-              "awesome.com"
-            ],
-            "w": 320,
-            "h": 50,
-            "ext": {
-              "prebid": {
-                "type": "banner"
-              }
-            }
-          },
-          "type": "banner"
-        },
-        {
-          "bid":  {
-            "id": "b4ae1b4e2fc24a4fb45540082e98e162",
-            "impid": "video-impression-id",
-            "price": 3.5,
-            "adm": "awesome-markup",
-            "crid": "20",
-            "adomain": [
-              "awesome.com"
-            ],
-            "w": 640,
-            "h": 480,
-            "ext": {
-              "prebid": {
-                "type": "video"
-              }
-            }
-          },
-          "type": "video"
-        }
-      ]
-    }
-  ]
-}
diff --git a/adapters/adagio/adagiotest/exemplary/native-web.json b/adapters/adagio/adagiotest/exemplary/native-web.json
deleted file mode 100644
index 0085aadd..00000000
--- a/adapters/adagio/adagiotest/exemplary/native-web.json
+++ /dev/null
@@ -1,151 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "device": {
-      "ua": "test-user-agent",
-      "ipv6": "2607:fb90:f27:4512:d800:cb23:a603:e245",
-      "language": "en",
-      "dnt": 0
-    },
-    "tmax": 1000,
-    "user": {
-      "buyeruid": "awesome-user"
-    },
-    "site": {
-      "page": "test.com",
-      "publisher": {
-        "id": "123456789"
-      }
-    },
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "native": {
-          "ver":"1.1",
-          "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "in_article"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ],
-          "X-Forwarded-For": [
-            "2607:fb90:f27:4512:d800:cb23:a603:e245"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "device": {
-            "ua": "test-user-agent",
-            "ipv6": "2607:fb90:f27:4512:d800:cb23:a603:e245",
-            "language": "en",
-            "dnt": 0
-          },
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "native": {
-                "ver":"1.1",
-                "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "in_article"
-                }
-              }
-            }
-          ],
-          "site": {
-            "page": "test.com",
-            "publisher": {
-              "id": "123456789"
-            }
-          },
-          "user": {
-            "buyeruid": "awesome-user"
-          },
-          "tmax": 1000
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "awesome-resp-id",
-          "seatbid": [
-            {
-              "bid": [
-                {
-                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-                  "impid": "some-impression-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "ext": {
-                    "prebid": {
-                      "type": "native"
-                    }
-                  }
-                }
-              ],
-              "seat": "adagio"
-            }
-          ],
-          "cur": "USD",
-          "ext": {
-            "responsetimemillis": {
-              "acuityads": 154
-            },
-            "tmaxrequest": 1000
-          }
-        }
-      }
-    }
-  ],
-  "expectedBidResponses": [
-    {
-      "bids":[
-        {
-          "bid":  {
-            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-            "impid": "some-impression-id",
-            "price": 3.5,
-            "adm": "awesome-markup",
-            "crid": "20",
-            "adomain": [
-              "awesome.com"
-            ],
-            "ext": {
-              "prebid": {
-                "type": "native"
-              }
-            }
-          },
-          "type": "native"
-        }
-      ]
-    }
-  ]
-}
diff --git a/adapters/adagio/adagiotest/exemplary/video-web.json b/adapters/adagio/adagiotest/exemplary/video-web.json
deleted file mode 100644
index 353420ee..00000000
--- a/adapters/adagio/adagiotest/exemplary/video-web.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "device": {
-      "ua": "test-user-agent",
-      "ip": "123.123.123.123",
-      "language": "en",
-      "dnt": 0
-    },
-    "tmax": 1000,
-    "user": {
-      "buyeruid": "awesome-user"
-    },
-    "site": {
-      "page": "test.com",
-      "publisher": {
-        "id": "123456789"
-      }
-    },
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "video": {
-          "mimes": [
-            "video\/mp4"
-          ],
-          "w": 640,
-          "h": 480,
-          "minduration": 120,
-          "maxduration": 150
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "in_article"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ],
-          "X-Forwarded-For": [
-            "123.123.123.123"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "device": {
-            "ua": "test-user-agent",
-            "ip": "123.123.123.123",
-            "language": "en",
-            "dnt": 0
-          },
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "video": {
-                "mimes": [
-                  "video\/mp4"
-                ],
-                "minduration": 120,
-                "maxduration": 150,
-                "w": 640,
-                "h": 480
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "in_article"
-                }
-              }
-            }
-          ],
-          "site": {
-            "page": "test.com",
-            "publisher": {
-              "id": "123456789"
-            }
-          },
-          "user": {
-            "buyeruid": "awesome-user"
-          },
-          "tmax": 1000
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "awesome-resp-id",
-          "seatbid": [
-            {
-              "bid": [
-                {
-                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-                  "impid": "some-impression-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "w": 1280,
-                  "h": 720,
-                  "ext": {
-                    "adagio": {
-                      "outstream": {
-                        "bvwUrl": "https://cool.io"
-                      }
-                    },
-                    "prebid": {
-                      "type": "video"
-                    }
-                  }
-                }
-              ],
-              "seat": "adagio"
-            }
-          ],
-          "cur": "USD",
-          "ext": {
-            "responsetimemillis": {
-              "adagio": 154
-            },
-            "tmaxrequest": 1000
-          }
-        }
-      }
-    }
-  ],
-  "expectedBidResponses": [
-    {
-      "bids": [
-        {
-          "bid": {
-            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-            "impid": "some-impression-id",
-            "price": 3.5,
-            "adm": "awesome-markup",
-            "adomain": [
-              "awesome.com"
-            ],
-            "crid": "20",
-            "w": 1280,
-            "h": 720,
-            "ext": {
-              "adagio": {
-                "outstream": {
-                  "bvwUrl": "https://cool.io"
-                }
-              },
-              "prebid": {
-                "type": "video"
-              }
-            }
-          },
-          "type":"video"
-        }
-      ]
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/adagio/adagiotest/supplemental/response-miss-ext-bid-type.json b/adapters/adagio/adagiotest/supplemental/response-miss-ext-bid-type.json
deleted file mode 100644
index 7b1267f6..00000000
--- a/adapters/adagio/adagiotest/supplemental/response-miss-ext-bid-type.json
+++ /dev/null
@@ -1,130 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "device": {
-      "ua": "test-user-agent",
-      "ip": "123.123.123.123",
-      "language": "en",
-      "dnt": 0
-    },
-    "tmax": 1000,
-    "user": {
-      "buyeruid": "awesome-user"
-    },
-    "site": {
-      "page": "test.com",
-      "publisher": {
-        "id": "123456789"
-      }
-    },
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ],
-          "X-Forwarded-For": [
-            "123.123.123.123"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "device": {
-            "ua": "test-user-agent",
-            "ip": "123.123.123.123",
-            "language": "en",
-            "dnt": 0
-          },
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ],
-          "site": {
-            "page": "test.com",
-            "publisher": {
-              "id": "123456789"
-            }
-          },
-          "user": {
-            "buyeruid": "awesome-user"
-          },
-          "tmax": 1000
-        }
-      },
-      "mockResponse": {
-        "status": 200,
-        "body": {
-          "id": "awesome-resp-id",
-          "seatbid": [
-            {
-              "bid": [
-                {
-                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
-                  "impid": "some-impression-id",
-                  "price": 3.5,
-                  "adm": "awesome-markup",
-                  "adomain": [
-                    "awesome.com"
-                  ],
-                  "crid": "20",
-                  "w": 320,
-                  "h": 50,
-                  "ext": {}
-                }
-              ],
-              "seat": "adagio"
-            }
-          ],
-          "cur": "USD",
-          "ext": {
-            "responsetimemillis": {
-              "adagio": 154
-            },
-            "tmaxrequest": 1000
-          }
-        }
-      }
-    }
-  ],
-  "expectedBidResponses": [
-    {
-      "bids": []
-    }
-  ]
-}
diff --git a/adapters/adagio/adagiotest/supplemental/status-204.json b/adapters/adagio/adagiotest/supplemental/status-204.json
deleted file mode 100644
index 4d604a01..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-204.json
+++ /dev/null
@@ -1,62 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 204,
-        "body": {}
-      }
-    }
-  ],
-  "expectedBidResponses": []
-}
diff --git a/adapters/adagio/adagiotest/supplemental/status-400.json b/adapters/adagio/adagiotest/supplemental/status-400.json
deleted file mode 100644
index 093c5458..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-400.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 400,
-        "body": "bad request"
-      }
-    }
-  ],
-  "expectedMakeBidsErrors": [
-    {
-      "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/adagio/adagiotest/supplemental/status-401.json b/adapters/adagio/adagiotest/supplemental/status-401.json
deleted file mode 100644
index a33aca20..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-401.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 401,
-        "body": "unauthorized"
-      }
-    }
-  ],
-  "expectedMakeBidsErrors": [
-    {
-      "value": "Unexpected status code: 401. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/adagio/adagiotest/supplemental/status-403.json b/adapters/adagio/adagiotest/supplemental/status-403.json
deleted file mode 100644
index 59c5a9cb..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-403.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 403,
-        "body": "forbidden"
-      }
-    }
-  ],
-  "expectedMakeBidsErrors": [
-    {
-      "value": "Unexpected status code: 403. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/adagio/adagiotest/supplemental/status-500.json b/adapters/adagio/adagiotest/supplemental/status-500.json
deleted file mode 100644
index 0077d745..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-500.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "debug": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 500,
-        "body": "internal error"
-      }
-    }
-  ],
-  "expectedMakeBidsErrors": [
-    {
-      "value": "Unexpected status code: 500. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/adagio/adagiotest/supplemental/status-503.json b/adapters/adagio/adagiotest/supplemental/status-503.json
deleted file mode 100644
index d2a52893..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-503.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 503,
-        "body": "Service unavailable"
-      }
-    }
-  ],
-  "expectedMakeBidsErrors": [
-    {
-      "value": "Unexpected status code: 503. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
-  ]
-}
diff --git a/adapters/adagio/adagiotest/supplemental/status-504.json b/adapters/adagio/adagiotest/supplemental/status-504.json
deleted file mode 100644
index 1b779d5c..00000000
--- a/adapters/adagio/adagiotest/supplemental/status-504.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "mockBidRequest": {
-    "test": 1,
-    "id": "some-request-id",
-    "imp": [
-      {
-        "id": "some-impression-id",
-        "banner": {
-          "w": 320,
-          "h": 50
-        },
-        "ext": {
-          "bidder": {
-            "organizationId": "1000",
-            "site": "site-name",
-            "placement": "ban_atf"
-          }
-        }
-      }
-    ]
-  },
-  "httpCalls": [
-    {
-      "expectedRequest": {
-        "headers": {
-          "Content-Type": [
-            "application/json;charset=utf-8"
-          ],
-          "Accept": [
-            "application/json"
-          ]
-        },
-        "uri": "http://localhost/prebid_server",
-        "body": {
-          "test": 1,
-          "id": "some-request-id",
-          "imp": [
-            {
-              "id": "some-impression-id",
-              "banner": {
-                "w": 320,
-                "h": 50
-              },
-              "ext": {
-                "bidder": {
-                  "organizationId": "1000",
-                  "site": "site-name",
-                  "placement": "ban_atf"
-                }
-              }
-            }
-          ]
-        }
-      },
-      "mockResponse": {
-        "status": 504,
-        "body": "gateway timeout"
-      }
-    }
-  ],
-  "expectedMakeBidsErrors": [
-    {
-      "value": "Unexpected status code: 504. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/adapters/adagio/params_test.go b/adapters/adagio/params_test.go
deleted file mode 100644
index ee8f702e..00000000
--- a/adapters/adagio/params_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package adagio
-
-import (
-	"encoding/json"
-	"testing"
-
-	"github.com/prebid/prebid-server/openrtb_ext"
-)
-
-var validParams = []string{
-	`{ "organizationId": "1234", "site": "adagio-io", "placement": "ban_atf" }`,
-	`{ "organizationId": "1234", "site": "adagio-io", "placement": "ban_atf", "_unknown": "ban_atf"}`,
-	`{ "organizationId": "1234", "site": "adagio-io", "placement": "ban_atf", "features": {"a": "a", "b": "b"}}`,
-}
-
-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.BidderAdagio, json.RawMessage(validParam)); err != nil {
-			t.Errorf("Schema rejected Adagio params: %s", validParam)
-		}
-	}
-}
-
-var invalidParams = []string{
-	``,
-	`null`,
-	`true`,
-	`5`,
-	`4.2`,
-	`[]`,
-	`{}`,
-	`{"adCode": "string", "seatCode": 5, "originalPublisherid": "string"}`,
-	`{ "organizationId": "", "site": "", "placement": "" }`,
-	`{ "organizationId": "", "site": "2", "placement": "3" }`,
-	`{ "organizationId": "1", "site": "", "placement": "3" }`,
-	`{ "organizationId": "1", "site": "2", "placement": "" }`,
-	`{ "organizationId": 1, "site": "2", "placement": "3" }`,
-	`{ "organizationId": "1234", "site": "adagio-io", "placement": "ban_atf", "features": {"a": "a", "notastring": true}}`,
-}
-
-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.BidderAdagio, json.RawMessage(invalidParam)); err == nil {
-			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
-		}
-	}
-}
diff --git a/adapters/algorix/algorixtest/exemplary/sample-banner-with-mediatype.json b/adapters/algorix/algorixtest/exemplary/sample-banner-with-mediatype.json
new file mode 100644
index 00000000..c9f9f877
--- /dev/null
+++ b/adapters/algorix/algorixtest/exemplary/sample-banner-with-mediatype.json
@@ -0,0 +1,105 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 320, "h": 50}]
+        },
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 320,
+          "h": 480
+        },
+        "ext": {
+          "bidder": {
+            "sid": "testSid",
+            "token": "testToken",
+            "region": "APAC"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://apac.xyz.test.com?sid=testSid&token=testToken",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "banner": {
+                "format": [{"w": 320, "h": 50}],
+                "w": 320,
+                "h": 50
+              },
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "w": 320,
+                "h": 480
+              },
+              "ext": {
+                "bidder": {
+                  "sid": "testSid",
+                  "token": "testToken",
+                  "region": "APAC"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-ads",
+                "crid": "crid_testid",
+                "ext": {
+                  "mediaType": "video"
+                }
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-ads",
+            "crid": "crid_testid",
+            "ext": {
+              "mediaType": "video"
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/algorix/algorixtest/exemplary/sample-rewarded-video.json b/adapters/algorix/algorixtest/exemplary/sample-rewarded-video.json
new file mode 100644
index 00000000..0d98de60
--- /dev/null
+++ b/adapters/algorix/algorixtest/exemplary/sample-rewarded-video.json
@@ -0,0 +1,102 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "w": 320,
+          "h": 480,
+          "mimes": [
+            "video/mp4"
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "sid": "testSid",
+            "token": "testToken",
+            "placementId": "testPlacementId",
+            "appId": "testAppId"
+          },
+          "prebid": {
+            "is_rewarded_inventory": 1
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "video": {
+                "w": 320,
+                "h": 480,
+                "mimes": [
+                  "video/mp4"
+                ],
+                "ext": {
+                  "rewarded": 1
+                }
+              },
+              "ext": {
+                "bidder": {
+                  "sid": "testSid",
+                  "token": "testToken",
+                  "placementId": "testPlacementId",
+                  "appId": "testAppId"
+                },
+                "prebid": {
+                  "is_rewarded_inventory": 1
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 1.2,
+                "adm": "some-ads",
+                "crid": "crid_testid"
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 1.2,
+            "adm": "some-ads",
+            "crid": "crid_testid"
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/algorix/algorixtest/supplemental/multiformat-no-mediatype-response.json b/adapters/algorix/algorixtest/supplemental/multiformat-no-mediatype-response.json
new file mode 100644
index 00000000..3828c52d
--- /dev/null
+++ b/adapters/algorix/algorixtest/supplemental/multiformat-no-mediatype-response.json
@@ -0,0 +1,90 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 320,
+          "h": 480
+        },
+        "banner": {
+          "format": [{"w": 320, "h": 50}]
+        },
+        "ext": {
+          "bidder": {
+            "sid": "testSid",
+            "token": "testToken",
+            "region": "APAC"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://apac.xyz.test.com?sid=testSid&token=testToken",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "banner": {
+                "format": [{"w": 320, "h": 50}],
+                "w": 320,
+                "h": 50
+              },
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "w": 320,
+                "h": 480
+              },
+              "ext": {
+                "bidder": {
+                  "sid": "testSid",
+                  "token": "testToken",
+                  "region": "APAC"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-ads",
+                "crid": "crid_testid",
+                "ext": {
+                }
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "comparison": "literal",
+      "value": "unable to fetch mediaType in multi-format: test-imp-id"
+    }
+  ]
+}
diff --git a/adapters/algorix/algorixtest/supplemental/sample-banner-with-other-mediatype.json b/adapters/algorix/algorixtest/supplemental/sample-banner-with-other-mediatype.json
new file mode 100644
index 00000000..df535318
--- /dev/null
+++ b/adapters/algorix/algorixtest/supplemental/sample-banner-with-other-mediatype.json
@@ -0,0 +1,91 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 320, "h": 50}]
+        },
+        "ext": {
+          "bidder": {
+            "sid": "testSid",
+            "token": "testToken",
+            "region": "APAC"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://apac.xyz.test.com?sid=testSid&token=testToken",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "banner": {
+                "format": [{"w": 320, "h": 50}],
+                "w": 320,
+                "h": 50
+              },
+              "ext": {
+                "bidder": {
+                  "sid": "testSid",
+                  "token": "testToken",
+                  "region": "APAC"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-ads",
+                "crid": "crid_testid",
+                "ext": {
+                  "mediaType": "video"
+                }
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-ads",
+            "crid": "crid_testid",
+            "ext": {
+              "mediaType": "video"
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/grid/gridtest/exemplary/multitype-banner.json b/adapters/grid/gridtest/exemplary/multitype-banner.json
new file mode 100644
index 00000000..c87e9f1e
--- /dev/null
+++ b/adapters/grid/gridtest/exemplary/multitype-banner.json
@@ -0,0 +1,100 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "site": {
+            "page": "https://good.site/url"
+        },
+        "imp": [{
+            "id": "test-imp-id",
+            "banner": {
+                "format": [{
+                    "w": 300,
+                    "h": 250
+                }]
+            },
+            "video": {
+                "mimes": ["video/mp4"],
+                "protocols": [2, 5],
+                "w": 300,
+                "h": 250
+            },
+            "ext": {
+                "bidder": {
+                    "uid": 1
+                }
+            }
+        }]
+    },
+
+    "httpCalls": [{
+        "expectedRequest": {
+            "uri": "http://localhost/prebid",
+            "body": {
+                "id": "test-request-id",
+                "site": {
+                    "page": "https://good.site/url"
+                },
+                "imp": [{
+                    "id": "test-imp-id",
+                    "banner": {
+                        "format": [{
+                            "w": 300,
+                            "h": 250
+                        }]
+                    },
+                    "video": {
+                        "mimes": ["video/mp4"],
+                        "protocols": [2, 5],
+                        "w": 300,
+                        "h": 250
+                    },
+                    "ext": {
+                        "bidder": {
+                            "uid": 1
+                        }
+                    }
+                }]
+            }
+        },
+        "mockResponse": {
+            "status": 200,
+            "body": {
+                "id": "test-request-id",
+                "seatbid": [{
+                    "seat": "grid",
+                    "bid": [{
+                        "id": "randomid",
+                        "impid": "test-imp-id",
+                        "price": 0.500000,
+                        "adid": "12345678",
+                        "adm": "some-test-ad",
+                        "cid": "987",
+                        "crid": "12345678",
+                        "content_type": "banner",
+                        "h": 250,
+                        "w": 300
+                    }]
+                }],
+                "cur": "USD"
+            }
+        }
+    }],
+
+    "expectedBidResponses": [{
+        "currency": "USD",
+        "bids": [{
+            "bid": {
+                "id": "randomid",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-test-ad",
+                "adid": "12345678",
+                "cid": "987",
+                "crid": "12345678",
+                "w": 300,
+                "h": 250
+            },
+            "type": "banner"
+        }]
+    }]
+}
diff --git a/adapters/grid/gridtest/exemplary/multitype-video.json b/adapters/grid/gridtest/exemplary/multitype-video.json
new file mode 100644
index 00000000..e822cd4b
--- /dev/null
+++ b/adapters/grid/gridtest/exemplary/multitype-video.json
@@ -0,0 +1,100 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "site": {
+            "page": "https://good.site/url"
+        },
+        "imp": [{
+            "id": "test-imp-id",
+            "banner": {
+                "format": [{
+                    "w": 300,
+                    "h": 250
+                }]
+            },
+            "video": {
+                "mimes": ["video/mp4"],
+                "protocols": [2, 5],
+                "w": 300,
+                "h": 250
+            },
+            "ext": {
+                "bidder": {
+                    "uid": 1
+                }
+            }
+        }]
+    },
+
+    "httpCalls": [{
+        "expectedRequest": {
+            "uri": "http://localhost/prebid",
+            "body": {
+                "id": "test-request-id",
+                "site": {
+                    "page": "https://good.site/url"
+                },
+                "imp": [{
+                    "id": "test-imp-id",
+                    "banner": {
+                        "format": [{
+                            "w": 300,
+                            "h": 250
+                        }]
+                    },
+                    "video": {
+                        "mimes": ["video/mp4"],
+                        "protocols": [2, 5],
+                        "w": 300,
+                        "h": 250
+                    },
+                    "ext": {
+                        "bidder": {
+                            "uid": 1
+                        }
+                    }
+                }]
+            }
+        },
+        "mockResponse": {
+            "status": 200,
+            "body": {
+                "id": "test-request-id",
+                "seatbid": [{
+                    "seat": "grid",
+                    "bid": [{
+                        "id": "randomid",
+                        "impid": "test-imp-id",
+                        "price": 0.500000,
+                        "adid": "12345678",
+                        "adm": "some-test-ad-vast",
+                        "cid": "987",
+                        "crid": "12345678",
+                        "content_type": "video",
+                        "h": 250,
+                        "w": 300
+                    }]
+                }],
+                "cur": "USD"
+            }
+        }
+    }],
+
+    "expectedBidResponses": [{
+        "currency": "USD",
+        "bids": [{
+            "bid": {
+                "id": "randomid",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-test-ad-vast",
+                "adid": "12345678",
+                "cid": "987",
+                "crid": "12345678",
+                "w": 300,
+                "h": 250
+            },
+            "type": "video"
+        }]
+    }]
+}
diff --git a/adapters/grid/gridtest/supplemental/bad_response.json b/adapters/grid/gridtest/supplemental/bad_response.json
index a9d38368..24863207 100644
--- a/adapters/grid/gridtest/supplemental/bad_response.json
+++ b/adapters/grid/gridtest/supplemental/bad_response.json
@@ -56,7 +56,7 @@
 
   "expectedMakeBidsErrors": [
     {
-      "value": "json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+      "value": "json: cannot unmarshal string into Go value of type grid.GridResponse",
       "comparison": "literal"
     }
   ]
diff --git a/adapters/huaweiads/huaweiads_test.go b/adapters/huaweiads/huaweiads_test.go
index 03b25d17..d3eeedff 100644
--- a/adapters/huaweiads/huaweiads_test.go
+++ b/adapters/huaweiads/huaweiads_test.go
@@ -4,15 +4,156 @@ 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.BidderHuaweiAds, config.Adapter{
-		Endpoint: "https://huaweiads.com/adxtest/"})
+		Endpoint: "https://huaweiads.com/adxtest/",
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"com.example.pkgname1\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"p3\",\"p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example1\",\"com.example2\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}," +
+			"{\"convertedPkgName\":\"com.example.pkgname2\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p9\",\"com.example.p10\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"p11\",\"p12\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example3\",\"com.example4\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p15\",\"com.example3.unchanged\"]}]}",
+	})
 
 	if buildErr != nil {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
 	}
 	adapterstest.RunJSONBidderTest(t, "huaweiadstest", bidder)
 }
+
+func TestExtraInfoDefaultWhenEmpty(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint:         `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: ``,
+	})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	bidderHuaweiAds, _ := bidder.(*adapter)
+
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert, []pkgNameConvert(nil))
+}
+
+func TestExtraInfo1(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint: `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"com.example.pkgname\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p3\",\"com.example.p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p5\",\"com.example.p6\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}]}",
+	})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	bidderHuaweiAds, _ := bidder.(*adapter)
+
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].ConvertedPkgName, "com.example.pkgname")
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].UnconvertedPkgNameKeyWords, []string{"com.example.p3", "com.example.p4"})
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].UnconvertedPkgNamePrefixs, []string{"com.example.p5", "com.example.p6"})
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].UnconvertedPkgNames, []string{"com.example.p1", "com.example.p2"})
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].ExceptionPkgNames, []string{"com.example.p7", "com.example.p8"})
+}
+
+func TestExtraInfo2(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint: `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"com.example.pkgname1\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p3\",\"com.example.p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p5\",\"com.example.p6\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}," +
+			"{\"convertedPkgName\":\"com.example.pkgname2\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p9\",\"com.example.p10\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p11\",\"com.example.p12\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p13\",\"com.example.p14\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p15\",\"com.example.p16\"]}]}",
+	})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	bidderHuaweiAds, _ := bidder.(*adapter)
+
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[1].ConvertedPkgName, "com.example.pkgname2")
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].UnconvertedPkgNameKeyWords, []string{"com.example.p3", "com.example.p4"})
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[1].UnconvertedPkgNamePrefixs, []string{"com.example.p13", "com.example.p14"})
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[0].UnconvertedPkgNames, []string{"com.example.p1", "com.example.p2"})
+	assert.Equal(t, bidderHuaweiAds.extraInfo.PkgNameConvert[1].ExceptionPkgNames, []string{"com.example.p15", "com.example.p16"})
+}
+
+func TestExtraInfo3(t *testing.T) {
+	_, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint: `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p3\",\"com.example.p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p5\",\"com.example.p6\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}]," +
+			"\"closeSiteSelectionByCountry\":\"1\"}",
+	})
+	assert.Equal(t, buildErr.Error(), "invalid extra info: ConvertedPkgName is empty, pls check")
+}
+
+func TestExtraInfo4(t *testing.T) {
+	_, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint: `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"com.example.pkgname1\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"\",\"com.example.p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p5\",\"\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}]," +
+			"\"closeSiteSelectionByCountry\":\"1\"}",
+	})
+	assert.Equal(t, buildErr.Error(), "invalid extra info: UnconvertedPkgNameKeyWords has a empty keyword, pls check")
+}
+
+func TestExtraInfo5(t *testing.T) {
+	_, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint: `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"com.example.pkgname1\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p3\",\"com.example.p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p5\",\"\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}]," +
+			"\"closeSiteSelectionByCountry\":\"1\"}",
+	})
+	assert.Equal(t, buildErr.Error(), "invalid extra info: UnconvertedPkgNamePrefixs has a empty value, pls check")
+}
+
+func TestExtraInfo6(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderHuaweiAds, config.Adapter{
+		Endpoint: `https://huaweiads.com/adxtest/`,
+		ExtraAdapterInfo: "{\"pkgNameConvert\":[{\"convertedPkgName\":\"com.example.pkgname1\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p1\",\"com.example.p2\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p3\",\"com.example.p4\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p5\",\"com.example.p6\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p7\",\"com.example.p8\"]}," +
+			"{\"convertedPkgName\":\"com.example.pkgname2\"," +
+			"\"unconvertedPkgNames\":[\"com.example.p9\",\"com.example.p10\"]," +
+			"\"unconvertedPkgNameKeyWords\":[\"com.example.p11\",\"com.example.p12\"]," +
+			"\"unconvertedPkgNamePrefixs\":[\"com.example.p13\",\"com.example.p14\"]," +
+			"\"exceptionPkgNames\":[\"com.example.p15\",\"com.example.p16\"]}],\"closeSiteSelectionByCountry\":\"1\"}",
+	})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	bidderHuaweiAds, _ := bidder.(*adapter)
+
+	assert.Equal(t, bidderHuaweiAds.extraInfo.CloseSiteSelectionByCountry, "1")
+}
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/banner1.json b/adapters/huaweiads/huaweiadstest/exemplary/banner1.json
index 866ff173..df1b40eb 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/banner1.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/banner1.json
@@ -27,7 +27,7 @@
       }
     ],
     "app": {
-      "bundle": "com.wavehk.android",
+      "bundle": "com.example.p1",
       "name": "Huawei Browser",
       "ver": "9.1.0.301",
       "content": {
@@ -38,7 +38,6 @@
       "ua": "useragent",
       "h": 1920,
       "language": "zh",
-      "geoCountry": "CH",
       "model": "COL-TEST",
       "os": "android",
       "osv": "10.0.0",
@@ -75,7 +74,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://acd.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
@@ -95,7 +94,7 @@
             "lang": "zh",
             "country": "CN",
             "name": "Huawei Browser",
-            "pkgname": "com.wavehk.android",
+            "pkgname": "com.example.pkgname1",
             "version": "9.1.0.301"
           },
           "multislot": [
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/banner2.json b/adapters/huaweiads/huaweiadstest/exemplary/banner2.json
index ab3dea21..65580187 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/banner2.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/banner2.json
@@ -55,7 +55,7 @@
       }
     },
     "app": {
-      "bundle": "org.prebid.mobile.prebidjavademo",
+      "bundle": "com.example.p10",
       "ver": "1.11",
       "name": "API1.0Demo",
       "publisher": {
@@ -99,7 +99,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
@@ -119,7 +119,7 @@
             "lang": "en",
             "country": "ZA",
             "name": "API1.0Demo",
-            "pkgname": "org.prebid.mobile.prebidjavademo",
+            "pkgname": "com.example.pkgname2",
             "version": "1.11"
           },
           "multislot": [
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo1.json b/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo1.json
new file mode 100644
index 00000000..10fceb5c
--- /dev/null
+++ b/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo1.json
@@ -0,0 +1,253 @@
+{
+  "mockBidRequest": {
+    "id": "test-req-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ],
+          "w": 300,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "slotid": "m8x9x3rzff",
+            "adtype": "banner",
+            "publisherid": "123",
+            "signkey": "signkey",
+            "keyid": "41",
+            "isTestAuthorization": "true"
+          }
+        }
+      }
+    ],
+    "app": {
+      "bundle": "com.example1.p",
+      "name": "Huawei name",
+      "ver": "9.1.0.301",
+      "content": {
+        "language": "zh"
+      }
+    },
+    "device": {
+      "ua": "useragent",
+      "h": 1920,
+      "language": "en",
+      "model": "COL-TEST",
+      "os": "android",
+      "osv": "10.0.0",
+      "devicetype": 4,
+      "make": "huawei",
+      "w": 1080,
+      "ip": "ip",
+      "pxratio": 23.01,
+      "geo": {
+        "country": "PRT"
+      }
+    },
+    "user": {
+      "ext": {
+        "data": {
+          "gaid": [
+            "gaid"
+          ],
+          "oaid": [
+            "oaid"
+          ],
+          "clientTime": [
+            "2018-11-02 16:34:07.981+1300"
+          ]
+        }
+      }
+    },
+    "regs": {
+      "coppa": 1
+    },
+    "ext": {
+    }
+  },
+  "httpcalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://adx-dre.op.hicloud.com/ppsadx/getResult",
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "useragent"
+          ],
+          "Authorization": [
+            "Digest username=123,realm=ppsadx/getResult,nonce=1629473330823,response=d1d61a13a83e1468aa4dff5c8a6cee0b8b381173ca3eb6fa9b313937684d87c0,algorithm=HmacSHA256,usertype=1,keyid=41"
+          ]
+        },
+        "body": {
+          "app": {
+            "lang": "zh",
+            "country": "PT",
+            "name": "Huawei name",
+            "pkgname": "com.example.pkgname1",
+            "version": "9.1.0.301"
+          },
+          "multislot": [
+            {
+              "adtype": 8,
+              "slotid": "m8x9x3rzff",
+              "test": 0,
+              "format": [
+                {
+                  "w": 300,
+                  "h": 250
+                }
+              ],
+              "w": 300,
+              "h": 250
+            }
+          ],
+          "device": {
+            "height": 1920,
+            "language": "en",
+            "oaid": "oaid",
+            "os": "android",
+            "type": 4,
+            "ip": "ip",
+            "localeCountry": "PT",
+            "pxratio": 23.01,
+            "width": 1080,
+            "clientTime": "2018-11-02 16:34:07.981+1300",
+            "gaid": "gaid",
+            "useragent": "useragent",
+            "version": "10.0.0",
+            "maker": "huawei",
+            "model": "COL-TEST",
+            "belongCountry": "PT"
+          },
+          "geo": {
+          },
+          "network": {
+            "type": 0
+          },
+          "regs": {
+            "coppa": 1
+          },
+          "version": "3.4"
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "ctrlSwitchs": "0",
+          "dsp1cost": 61,
+          "dspcost": 108,
+          "multiad": [
+            {
+              "adtype": 8,
+              "brsetting": "Y",
+              "content": [
+                {
+                  "clickActionList": [
+                    1
+                  ],
+                  "contentid": "58025103",
+                  "creativetype": 2,
+                  "ctrlSwitchs": "001011001001010112",
+                  "endtime": 1621428898335,
+                  "filterList": [
+                    3
+                  ],
+                  "interactiontype": 1,
+                  "landingTitle": 1,
+                  "metaData": {
+                    "adSign": "2",
+                    "appPromotionChannel": "401721412",
+                    "clickUrl": "https://ads.huawei.com/usermgtportal/home/index.html#/",
+                    "imageInfo": [
+                      {
+                        "checkSha256Flag": 1,
+                        "height": 300,
+                        "imageType": "img",
+                        "sha256": "f5d8487cddaecec45b73fc078649478c80ec646bfec8ed7da4ff931f90eab232",
+                        "url": "https://ads.huawei.com/usermgtportal/home/img/huawei_logo_black.aaec817d.svg",
+                        "width": 250
+                      }
+                    ],
+                    "label": "Banner_API",
+                    "landingPageType": "3"
+                  },
+                  "monitor": [
+                    {
+                      "eventType": "click",
+                      "url": [
+                        "http://test/click1",
+                        "http://test/click2",
+                        "http://test/click3"
+                      ]
+                    },
+                    {
+                      "eventType": "imp",
+                      "url": [
+                        "http://test/imp1",
+                        "http://test/imp2",
+                        "http://test/imp3"
+                      ]
+                    }
+                  ],
+                  "paramfromserver": {
+                    "a": "1||test",
+                    "sig": "",
+                    "t": "99990101235959"
+                  },
+                  "price": 2.8,
+                  "starttime": 1621267200000,
+                  "taskid": "48017658"
+                }
+              ],
+              "retcode30": 200,
+              "slotid": "m8x9x3rzff"
+            }
+          ],
+          "noReportAdTypeEventList": [
+            {
+              "adType": 8,
+              "eventTypeList": [
+                "exception_6"
+              ]
+            }
+          ],
+          "retcode": 200,
+          "totalCacheSize": 300
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "adm": "<style> html, body  { margin: 0; padding: 0; width: 100%; height: 100%; vertical-align: middle; }  html  { display: table; }  body { display: table-cell; vertical-align: middle; text-align: center; -webkit-text-size-adjust: none; }  </style> <span class=\"title-link advertiser_label\"></span> <a href='https://ads.huawei.com/usermgtportal/home/index.html#/' style=\"text-decoration:none\" onclick=sendGetReq()> <img src='https://ads.huawei.com/usermgtportal/home/img/huawei_logo_black.aaec817d.svg' width='250' height='300'/> </a> <img height=\"1\" width=\"1\" src='http://test/imp1' >  <img height=\"1\" width=\"1\" src='http://test/imp2' >  <img height=\"1\" width=\"1\" src='http://test/imp3' >  <script type=\"text/javascript\">var dspClickTrackings = [\"http://test/click1\",\"http://test/click2\",\"http://test/click3\"];function sendGetReq() {sendSomeGetReq(dspClickTrackings)}function sendOneGetReq(url) {var req = new XMLHttpRequest();req.open('GET', url, true);req.send(null);}function sendSomeGetReq(urls) {for (var i = 0; i < urls.length; i++) {sendOneGetReq(urls[i]);}}</script>",
+            "adomain": [
+              "huaweiads"
+            ],
+            "crid": "58025103",
+            "id": "test-imp-id",
+            "impid": "test-imp-id",
+            "price": 2.8,
+            "h": 300,
+            "w": 250
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo2.json b/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo2.json
new file mode 100644
index 00000000..a05ca8d9
--- /dev/null
+++ b/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo2.json
@@ -0,0 +1,271 @@
+{
+  "mockBidRequest": {
+    "id": "a3b18c5b-6708-4bb7-b41b-40ed37d89561",
+    "source": {
+      "tid": "a3b18c5b-6708-4bb7-b41b-40ed37d89561"
+    },
+    "imp": [
+      {
+        "id": "PrebidMobile",
+        "secure": 1,
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ],
+          "api": [
+            5
+          ]
+        },
+        "ext": {
+          "prebid": {
+            "storedrequest": {
+              "id": "1001-1"
+            }
+          },
+          "bidder": {
+            "slotid": "m8x9x3rzff",
+            "adtype": "banner",
+            "publisherid": "123",
+            "signkey": "signkey",
+            "keyid": "41",
+            "isTestAuthorization": "true"
+          }
+        }
+      }
+    ],
+    "device": {
+      "make": "HUAWEI",
+      "model": "LYA-AL00",
+      "ua": "ua",
+      "lmt": 0,
+      "os": "android",
+      "osv": "29",
+      "language": "en",
+      "w": 360,
+      "h": 755,
+      "pxratio": 3,
+      "mccmnc": "424-3",
+      "carrier": "carrier",
+      "connectiontype": 1,
+      "geo": {
+        "country": "RUS"
+      }
+    },
+    "app": {
+      "bundle": "com.example4.p",
+      "ver": "1.11",
+      "name": "API1.0Demo",
+      "publisher": {
+        "id": "1001"
+      },
+      "ext": {
+        "prebid": {
+          "source": "prebid-mobile",
+          "version": "1.11"
+        }
+      }
+    },
+    "user": {
+      "gender": "O",
+      "ext": {
+        "data": {
+          "gaid": [
+            "gaid"
+          ],
+          "oaid": [
+            "oaid"
+          ],
+          "clientTime": [
+            "2018-11-02 16:34:07.981+1300"
+          ]
+        }
+      }
+    },
+    "ext": {
+      "prebid": {
+        "storedrequest": {
+          "id": "1001"
+        },
+        "cache": {
+          "bids": {}
+        },
+        "targeting": {}
+      }
+    }
+  },
+  "httpcalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://adx-drru.op.hicloud.com/ppsadx/getResult",
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "ua"
+          ],
+          "Authorization": [
+            "Digest username=123,realm=ppsadx/getResult,nonce=1629473330823,response=d1d61a13a83e1468aa4dff5c8a6cee0b8b381173ca3eb6fa9b313937684d87c0,algorithm=HmacSHA256,usertype=1,keyid=41"
+          ]
+        },
+        "body": {
+          "app": {
+            "lang": "en",
+            "country": "RU",
+            "name": "API1.0Demo",
+            "pkgname": "com.example.pkgname2",
+            "version": "1.11"
+          },
+          "multislot": [
+            {
+              "adtype": 8,
+              "slotid": "m8x9x3rzff",
+              "test": 0,
+              "format": [
+                {
+                  "w": 300,
+                  "h": 250
+                }
+              ]
+            }
+          ],
+          "device": {
+            "height": 755,
+            "language": "en",
+            "oaid": "oaid",
+            "os": "android",
+            "localeCountry": "RU",
+            "pxratio": 3,
+            "width": 360,
+            "model": "LYA-AL00",
+            "clientTime": "2018-11-02 16:34:07.981+1300",
+            "gaid": "gaid",
+            "useragent": "ua",
+            "version": "29",
+            "maker": "HUAWEI",
+            "belongCountry": "RU"
+          },
+          "geo": {
+          },
+          "network": {
+            "carrier": 99,
+            "cellInfo": [
+              {
+                "mcc": "424",
+                "mnc": "3"
+              }
+            ],
+            "type": 1
+          },
+          "regs": {
+          },
+          "version": "3.4"
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "ctrlSwitchs": "0",
+          "dsp1cost": 61,
+          "dspcost": 108,
+          "multiad": [
+            {
+              "adtype": 8,
+              "brsetting": "Y",
+              "content": [
+                {
+                  "clickActionList": [
+                    1
+                  ],
+                  "contentid": "58025103",
+                  "creativetype": 2,
+                  "endtime": 1621428898335,
+                  "filterList": [
+                    3
+                  ],
+                  "interactiontype": 1,
+                  "landingTitle": 1,
+                  "metaData": {
+                    "adSign": "2",
+                    "appPromotionChannel": "401721412",
+                    "clickUrl": "https://ads.huawei.com/usermgtportal/home/index.html#/",
+                    "imageInfo": [
+                      {
+                        "checkSha256Flag": 1,
+                        "height": 250,
+                        "imageType": "img",
+                        "sha256": "",
+                        "url": "https://ads.huawei.com/usermgtportal/home/img/huawei_logo_black.aaec817d.svg",
+                        "width": 300
+                      }
+                    ],
+                    "label": "Banner_API",
+                    "landingPageType": "3"
+                  },
+                  "monitor": [
+                    {
+                      "eventType": "click"
+                    },
+                    {
+                      "eventType": "imp",
+                      "url": [
+                      ]
+                    }
+                  ],
+                  "paramfromserver": {
+                    "a": "1||test",
+                    "sig": "",
+                    "t": "99990101235959"
+                  },
+                  "price": 2.8,
+                  "starttime": 1621267200000,
+                  "taskid": "48017658"
+                }
+              ],
+              "retcode30": 200,
+              "slotid": "m8x9x3rzff"
+            }
+          ],
+          "noReportAdTypeEventList": [
+            {
+              "adType": 8,
+              "eventTypeList": [
+                "exception_6"
+              ]
+            }
+          ],
+          "retcode": 200,
+          "totalCacheSize": 300
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "adm": "<style> html, body  { margin: 0; padding: 0; width: 100%; height: 100%; vertical-align: middle; }  html  { display: table; }  body { display: table-cell; vertical-align: middle; text-align: center; -webkit-text-size-adjust: none; }  </style> <span class=\"title-link advertiser_label\"></span> <a href='https://ads.huawei.com/usermgtportal/home/index.html#/' style=\"text-decoration:none\" onclick=sendGetReq()> <img src='https://ads.huawei.com/usermgtportal/home/img/huawei_logo_black.aaec817d.svg' width='300' height='250'/> </a> <script type=\"text/javascript\">var dspClickTrackings = [];function sendGetReq() {sendSomeGetReq(dspClickTrackings)}function sendOneGetReq(url) {var req = new XMLHttpRequest();req.open('GET', url, true);req.send(null);}function sendSomeGetReq(urls) {for (var i = 0; i < urls.length; i++) {sendOneGetReq(urls[i]);}}</script>",
+            "adomain": [
+              "huaweiads"
+            ],
+            "h": 250,
+            "w": 300,
+            "crid": "58025103",
+            "id": "PrebidMobile",
+            "impid": "PrebidMobile",
+            "price": 2.8
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo3.json b/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo3.json
new file mode 100644
index 00000000..6ab59e5c
--- /dev/null
+++ b/adapters/huaweiads/huaweiadstest/exemplary/bannerTestExtraInfo3.json
@@ -0,0 +1,271 @@
+{
+  "mockBidRequest": {
+    "id": "a3b18c5b-6708-4bb7-b41b-40ed37d89561",
+    "source": {
+      "tid": "a3b18c5b-6708-4bb7-b41b-40ed37d89561"
+    },
+    "imp": [
+      {
+        "id": "PrebidMobile",
+        "secure": 1,
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ],
+          "api": [
+            5
+          ]
+        },
+        "ext": {
+          "prebid": {
+            "storedrequest": {
+              "id": "1001-1"
+            }
+          },
+          "bidder": {
+            "slotid": "m8x9x3rzff",
+            "adtype": "banner",
+            "publisherid": "123",
+            "signkey": "signkey",
+            "keyid": "41",
+            "isTestAuthorization": "true"
+          }
+        }
+      }
+    ],
+    "device": {
+      "make": "HUAWEI",
+      "model": "LYA-AL00",
+      "ua": "ua",
+      "lmt": 0,
+      "os": "android",
+      "osv": "29",
+      "language": "en",
+      "w": 360,
+      "h": 755,
+      "pxratio": 3,
+      "mccmnc": "424-3",
+      "carrier": "carrier",
+      "connectiontype": 1,
+      "geo": {
+        "country": "TUN"
+      }
+    },
+    "app": {
+      "bundle": "com.example3.unchanged",
+      "ver": "1.11",
+      "name": "API1.0Demo",
+      "publisher": {
+        "id": "1001"
+      },
+      "ext": {
+        "prebid": {
+          "source": "prebid-mobile",
+          "version": "1.11"
+        }
+      }
+    },
+    "user": {
+      "gender": "O",
+      "ext": {
+        "data": {
+          "gaid": [
+            "gaid"
+          ],
+          "oaid": [
+            "oaid"
+          ],
+          "clientTime": [
+            "2018-11-02 16:34:07.981+1300"
+          ]
+        }
+      }
+    },
+    "ext": {
+      "prebid": {
+        "storedrequest": {
+          "id": "1001"
+        },
+        "cache": {
+          "bids": {}
+        },
+        "targeting": {}
+      }
+    }
+  },
+  "httpcalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "ua"
+          ],
+          "Authorization": [
+            "Digest username=123,realm=ppsadx/getResult,nonce=1629473330823,response=d1d61a13a83e1468aa4dff5c8a6cee0b8b381173ca3eb6fa9b313937684d87c0,algorithm=HmacSHA256,usertype=1,keyid=41"
+          ]
+        },
+        "body": {
+          "app": {
+            "lang": "en",
+            "country": "TN",
+            "name": "API1.0Demo",
+            "pkgname": "com.example3.unchanged",
+            "version": "1.11"
+          },
+          "multislot": [
+            {
+              "adtype": 8,
+              "slotid": "m8x9x3rzff",
+              "test": 0,
+              "format": [
+                {
+                  "w": 300,
+                  "h": 250
+                }
+              ]
+            }
+          ],
+          "device": {
+            "height": 755,
+            "language": "en",
+            "oaid": "oaid",
+            "os": "android",
+            "localeCountry": "TN",
+            "pxratio": 3,
+            "width": 360,
+            "model": "LYA-AL00",
+            "clientTime": "2018-11-02 16:34:07.981+1300",
+            "gaid": "gaid",
+            "useragent": "ua",
+            "version": "29",
+            "maker": "HUAWEI",
+            "belongCountry": "TN"
+          },
+          "geo": {
+          },
+          "network": {
+            "carrier": 99,
+            "cellInfo": [
+              {
+                "mcc": "424",
+                "mnc": "3"
+              }
+            ],
+            "type": 1
+          },
+          "regs": {
+          },
+          "version": "3.4"
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "ctrlSwitchs": "0",
+          "dsp1cost": 61,
+          "dspcost": 108,
+          "multiad": [
+            {
+              "adtype": 8,
+              "brsetting": "Y",
+              "content": [
+                {
+                  "clickActionList": [
+                    1
+                  ],
+                  "contentid": "58025103",
+                  "creativetype": 2,
+                  "endtime": 1621428898335,
+                  "filterList": [
+                    3
+                  ],
+                  "interactiontype": 1,
+                  "landingTitle": 1,
+                  "metaData": {
+                    "adSign": "2",
+                    "appPromotionChannel": "401721412",
+                    "clickUrl": "https://ads.huawei.com/usermgtportal/home/index.html#/",
+                    "imageInfo": [
+                      {
+                        "checkSha256Flag": 1,
+                        "height": 250,
+                        "imageType": "img",
+                        "sha256": "",
+                        "url": "https://ads.huawei.com/usermgtportal/home/img/huawei_logo_black.aaec817d.svg",
+                        "width": 300
+                      }
+                    ],
+                    "label": "Banner_API",
+                    "landingPageType": "3"
+                  },
+                  "monitor": [
+                    {
+                      "eventType": "click"
+                    },
+                    {
+                      "eventType": "imp",
+                      "url": [
+                      ]
+                    }
+                  ],
+                  "paramfromserver": {
+                    "a": "1||test",
+                    "sig": "",
+                    "t": "99990101235959"
+                  },
+                  "price": 2.8,
+                  "starttime": 1621267200000,
+                  "taskid": "48017658"
+                }
+              ],
+              "retcode30": 200,
+              "slotid": "m8x9x3rzff"
+            }
+          ],
+          "noReportAdTypeEventList": [
+            {
+              "adType": 8,
+              "eventTypeList": [
+                "exception_6"
+              ]
+            }
+          ],
+          "retcode": 200,
+          "totalCacheSize": 300
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "adm": "<style> html, body  { margin: 0; padding: 0; width: 100%; height: 100%; vertical-align: middle; }  html  { display: table; }  body { display: table-cell; vertical-align: middle; text-align: center; -webkit-text-size-adjust: none; }  </style> <span class=\"title-link advertiser_label\"></span> <a href='https://ads.huawei.com/usermgtportal/home/index.html#/' style=\"text-decoration:none\" onclick=sendGetReq()> <img src='https://ads.huawei.com/usermgtportal/home/img/huawei_logo_black.aaec817d.svg' width='300' height='250'/> </a> <script type=\"text/javascript\">var dspClickTrackings = [];function sendGetReq() {sendSomeGetReq(dspClickTrackings)}function sendOneGetReq(url) {var req = new XMLHttpRequest();req.open('GET', url, true);req.send(null);}function sendSomeGetReq(urls) {for (var i = 0; i < urls.length; i++) {sendOneGetReq(urls[i]);}}</script>",
+            "adomain": [
+              "huaweiads"
+            ],
+            "h": 250,
+            "w": 300,
+            "crid": "58025103",
+            "id": "PrebidMobile",
+            "impid": "PrebidMobile",
+            "price": 2.8
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json
index d804375c..ae3efabc 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json
@@ -65,7 +65,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json
index 62e2dcd6..ff8e686c 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json
@@ -28,8 +28,7 @@
     "device": {
       "ua": "useragent",
       "h": 1920,
-      "language": "zh",
-      "geoCountry": "CH",
+      "language": "en",
       "model": "COL-TEST",
       "os": "android",
       "osv": "10.0.0",
@@ -40,7 +39,7 @@
       "dnt": 0,
       "pxratio": 23.01,
       "geo": {
-        "country": ""
+        "country": "DEU"
       }
     },
     "user": {
@@ -64,7 +63,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dre.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
@@ -82,7 +81,7 @@
         "body": {
           "app": {
             "lang": "en",
-            "country": "ZA",
+            "country": "DE",
             "name": "Huawei Browser",
             "pkgname": "com.huawei.browser",
             "version": "9.1.0.301"
@@ -101,12 +100,12 @@
           ],
           "device": {
             "height": 1920,
-            "language": "zh",
+            "language": "en",
             "oaid": "oaid",
             "os": "android",
             "type": 4,
             "ip": "ip",
-            "localeCountry": "ZA",
+            "localeCountry": "DE",
             "pxratio": 23.01,
             "model": "COL-TEST",
             "width": 1080,
@@ -117,7 +116,7 @@
             "useragent": "useragent",
             "version": "10.0.0",
             "maker": "huawei",
-            "belongCountry": "ZA"
+            "belongCountry": "DE"
           },
           "geo": {
           },
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json
index a68d8b8a..22ac3556 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json
@@ -21,15 +21,14 @@
       }
     ],
     "app": {
-      "bundle": "com.huawei.browser",
+      "bundle": "com.huawei.p11",
       "name": "Huawei Browser",
       "ver": "9.1.0.301"
     },
     "device": {
       "ua": "useragent",
       "h": 1920,
-      "language": "zh",
-      "geoCountry": "CH",
+      "language": "en",
       "model": "COL-TEST",
       "os": "android",
       "osv": "10.0.0",
@@ -39,7 +38,7 @@
       "ip": "152.193.6.74",
       "pxratio": 23.01,
       "geo": {
-        "country": ""
+        "country": "ARG"
       }
     },
     "user": {
@@ -63,7 +62,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
@@ -81,9 +80,9 @@
         "body": {
           "app": {
             "lang": "en",
-            "country": "ZA",
+            "country": "AR",
             "name": "Huawei Browser",
-            "pkgname": "com.huawei.browser",
+            "pkgname": "com.example.pkgname2",
             "version": "9.1.0.301"
           },
           "multislot": [
@@ -100,12 +99,12 @@
           ],
           "device": {
             "height": 1920,
-            "language": "zh",
+            "language": "en",
             "oaid": "oaid",
             "os": "android",
             "type": 4,
             "ip": "152.193.6.74",
-            "localeCountry": "ZA",
+            "localeCountry": "AR",
             "pxratio": 23.01,
             "model": "COL-TEST",
             "width": 1080,
@@ -114,7 +113,7 @@
             "useragent": "useragent",
             "version": "10.0.0",
             "maker": "huawei",
-            "belongCountry": "ZA"
+            "belongCountry": "AR"
           },
           "geo": {
           },
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json
index a6372030..18f03538 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json
@@ -63,7 +63,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/video.json b/adapters/huaweiads/huaweiadstest/exemplary/video.json
index ec589d3d..64c54d5d 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/video.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/video.json
@@ -39,8 +39,7 @@
     "device": {
       "ua": "useragent",
       "h": 1920,
-      "language": "zh",
-      "geoCountry": "CH",
+      "language": "en",
       "model": "COL-TEST",
       "os": "android",
       "osv": "10.0.0",
@@ -50,7 +49,7 @@
       "ip": "ip",
       "pxratio": 23.01,
       "geo": {
-        "country": ""
+        "country": "ATA"
       }
     },
     "user": {
@@ -74,7 +73,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dre.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
@@ -92,7 +91,7 @@
         "body": {
           "app": {
             "lang": "en",
-            "country": "ZA",
+            "country": "AT",
             "name": "Huawei Browser",
             "pkgname": "com.wavehk.android",
             "version": "9.1.0.301"
@@ -106,12 +105,12 @@
           ],
           "device": {
             "height": 1920,
-            "language": "zh",
+            "language": "en",
             "oaid": "oaid",
             "os": "android",
             "type": 4,
             "ip": "ip",
-            "localeCountry": "ZA",
+            "localeCountry": "AT",
             "pxratio": 23.01,
             "width": 1080,
             "model": "COL-TEST",
@@ -120,7 +119,7 @@
             "useragent": "useragent",
             "version": "10.0.0",
             "maker": "huawei",
-            "belongCountry": "ZA"
+            "belongCountry": "AT"
           },
           "geo": {
           },
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response.json
index b064adb2..327004f9 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_400.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_400.json
index 6b42905b..e06af96a 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_400.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_400.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_503.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_503.json
index 032c8e9a..53b05eba 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_503.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_503.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_dont_find_impid.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_dont_find_impid.json
index 7d691d11..c2cc3424 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_dont_find_impid.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_dont_find_impid.json
@@ -92,7 +92,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json
index e4e6ec18..f4e5457c 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json
@@ -63,7 +63,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode30_204.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode30_204.json
index 5a04ff6b..adb456cb 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode30_204.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode30_204.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_210.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_210.json
index ff0fd39f..4d4cc062 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_210.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_210.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_408.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_408.json
index 7878aa88..e8778e46 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_408.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_408.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_500.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_500.json
index c3b9de07..cd6440d1 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_500.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_retcode_500.json
@@ -69,7 +69,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://huaweiads.com/adxtest/",
+        "uri": "https://adx-dra.op.hicloud.com/ppsadx/getResult",
         "headers": {
           "Accept": [
             "application/json"
diff --git a/adapters/vidoomy/params_test.go b/adapters/vidoomy/params_test.go
new file mode 100644
index 00000000..d910b654
--- /dev/null
+++ b/adapters/vidoomy/params_test.go
@@ -0,0 +1,57 @@
+package vidoomy
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// This file actually intends to test static/bidder-params/vidoomy.json
+//
+// These also validate the format of the external API: request.imp[i].ext.vidoomy
+
+// TestValidParams makes sure that the vidoomy 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.BidderVidoomy, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected vidoomy params: %s", validParam)
+		}
+	}
+}
+
+// TestInvalidParams makes sure that the Vidoomy 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.BidderVidoomy, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"zoneId":"123"}`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"notmid":"123"}`,
+	`{"zoneId":123}`,
+	`{"zoneId":""}`,
+}
diff --git a/adapters/vidoomy/vidoomy_test.go b/adapters/vidoomy/vidoomy_test.go
new file mode 100644
index 00000000..c9181395
--- /dev/null
+++ b/adapters/vidoomy/vidoomy_test.go
@@ -0,0 +1,34 @@
+package vidoomy
+
+import (
+	"testing"
+
+	"github.com/influxdata/influxdb/pkg/testing/assert"
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestVidoomyBidderEndpointConfig(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderVidoomy, config.Adapter{
+		Endpoint: "http://localhost/bid",
+	})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	bidderVidoomy := bidder.(*adapter)
+
+	assert.Equal(t, "http://localhost/bid", bidderVidoomy.endpoint)
+}
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderVidoomy, config.Adapter{})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "vidoomytest", bidder)
+}
diff --git a/adapters/vidoomy/vidoomytest/exemplary/multi-impression-video-banner.json b/adapters/vidoomy/vidoomytest/exemplary/multi-impression-video-banner.json
new file mode 100644
index 00000000..723248dd
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/exemplary/multi-impression-video-banner.json
@@ -0,0 +1,226 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      },
+      {
+        "id": "test-imp-video-id",
+        "video": {
+          "w": 900,
+          "h": 250,
+          "mimes": [
+            "video/x-flv",
+            "video/mp4"
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "test-site-id"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "X-Forwarded-For": [
+            "127.0.0.1"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ip": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}],
+                "w": 728,
+                "h": 90
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "test-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "vidoomy",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    },
+    {
+      "expectedRequest": {
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "X-Forwarded-For": [
+            "127.0.0.1"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ip": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-video-id",
+              "video": {
+                "w": 900,
+                "h": 250,
+                "mimes": [
+                  "video/x-flv",
+                  "video/mp4"
+                ]
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "test-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "cur": "USD",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "fe69dd6d-e85c-4186-80a7-605b530bc23b",
+                  "crid": "72745",
+                  "adomain": [
+                    "ad-domain.com"
+                  ],
+                  "price": 3,
+                  "impid": "test-imp-video-id",
+                  "adid": "564",
+                  "adm": "<?xml version=\"1.0\"?><VAST version=\"2.0\"></VAST>"
+                }
+              ],
+              "seat": "vidoomy"
+            }
+          ],
+          "id": "test-request-id"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90
+          },
+          "type": "banner"
+        }
+      ]
+    },
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "fe69dd6d-e85c-4186-80a7-605b530bc23b",
+            "crid": "72745",
+            "adomain": [
+              "ad-domain.com"
+            ],
+            "price": 3,
+            "impid": "test-imp-video-id",
+            "adid": "564",
+            "adm": "<?xml version=\"1.0\"?><VAST version=\"2.0\"></VAST>"
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/vidoomy/vidoomytest/exemplary/simple-app-banner.json b/adapters/vidoomy/vidoomytest/exemplary/simple-app-banner.json
new file mode 100644
index 00000000..145524ea
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/exemplary/simple-app-banner.json
@@ -0,0 +1,116 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "app": {
+      "id": "test-app-id"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "X-Forwarded-For": [
+            "127.0.0.1"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ip": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}],
+                "w": 728,
+                "h": 90
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "test-app-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "vidoomy",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/vidoomy/vidoomytest/exemplary/simple-banner.json b/adapters/vidoomy/vidoomytest/exemplary/simple-banner.json
new file mode 100644
index 00000000..36d27856
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/exemplary/simple-banner.json
@@ -0,0 +1,116 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "test-site-id"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "X-Forwarded-For": [
+            "127.0.0.1"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ip": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}],
+                "w": 728,
+                "h": 90
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "test-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "vidoomy",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/exemplary/simple-site-video.json b/adapters/vidoomy/vidoomytest/exemplary/simple-site-video.json
new file mode 100644
index 00000000..d2d6e028
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/exemplary/simple-site-video.json
@@ -0,0 +1,121 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-video-id",
+        "video": {
+          "w": 900,
+          "h": 250,
+          "mimes": [
+            "video/x-flv",
+            "video/mp4"
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "site": {
+      "id": "test",
+      "publisher": {
+        "id": "123"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "method": "GET",
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-video-id",
+              "video": {
+                "w": 900,
+                "h": 250,
+                "mimes": [
+                  "video/x-flv",
+                  "video/mp4"
+                ]
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "test",
+            "publisher": {
+              "id": "123"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "cur": "USD",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "fe69dd6d-e85c-4186-80a7-605b530bc23b",
+                  "crid": "72745",
+                  "adomain": [
+                    "ad-domain.com"
+                  ],
+                  "price": 3,
+                  "impid": "test-imp-video-id",
+                  "adid": "564",
+                  "adm": "<?xml version=\"1.0\"?><VAST version=\"2.0\"></VAST>"
+                }
+              ],
+              "seat": "vidoomy"
+            }
+          ],
+          "id": "test-request-id"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "fe69dd6d-e85c-4186-80a7-605b530bc23b",
+            "crid": "72745",
+            "adomain": [
+              "ad-domain.com"
+            ],
+            "price": 3,
+            "impid": "test-imp-video-id",
+            "adid": "564",
+            "adm": "<?xml version=\"1.0\"?><VAST version=\"2.0\"></VAST>"
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/supplemental/server-error.json b/adapters/vidoomy/vidoomytest/supplemental/server-error.json
new file mode 100644
index 00000000..ebeedb14
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/supplemental/server-error.json
@@ -0,0 +1,70 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "site-id"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ip": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}],
+                "w": 728,
+                "h": 90
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 500,
+        "body": {
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 500.",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/supplemental/server-response-wrong-impid.json b/adapters/vidoomy/vidoomytest/supplemental/server-response-wrong-impid.json
new file mode 100644
index 00000000..dad8f7cc
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/supplemental/server-response-wrong-impid.json
@@ -0,0 +1,103 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "site-id"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "X-Forwarded-For": [
+            "127.0.0.1"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ip": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}],
+                "w": 728,
+                "h": 90
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "vidoomy",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "wrong",
+                "price": 0.500000,
+                "adm": "some-test-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unknown ad unit code 'wrong'",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/supplemental/simple-banner-no-response.json b/adapters/vidoomy/vidoomytest/supplemental/simple-banner-no-response.json
new file mode 100644
index 00000000..0964351a
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/supplemental/simple-banner-no-response.json
@@ -0,0 +1,85 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}],
+          "w": 728,
+          "h": 90
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ipv6": "127.0.0.1"
+    },
+    "site": {
+      "id": "test-site-id"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "X-Forwarded-For": [
+            "127.0.0.1"
+          ]
+        },
+        "uri": "",
+        "body": {
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+            "ipv6": "127.0.0.1"
+          },
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}],
+                "w": 728,
+                "h": 90
+              },
+              "ext": {
+                "bidder": {
+                  "zoneId": "zone-id-123"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "test-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {}
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-format.json b/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-format.json
new file mode 100644
index 00000000..e38f37f4
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-format.json
@@ -0,0 +1,32 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": []
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "test-site-id"
+    }
+  },
+
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "no sizes provided for Banner []",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-width-high.json b/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-width-high.json
new file mode 100644
index 00000000..b5c22546
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-width-high.json
@@ -0,0 +1,34 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}],
+          "w": 0,
+          "h": 720
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "test-site-id"
+    }
+  },
+
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "invalid sizes provided for Banner 0 x 720",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-with-format.json b/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-with-format.json
new file mode 100644
index 00000000..e4541c9c
--- /dev/null
+++ b/adapters/vidoomy/vidoomytest/supplemental/wrong-banner-with-format.json
@@ -0,0 +1,34 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}],
+          "w": 0,
+          "h" : 90
+        },
+        "ext": {
+          "bidder": {
+            "zoneId": "zone-id-123"
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+      "ip": "127.0.0.1"
+    },
+    "site": {
+      "id": "test-site-id"
+    }
+  },
+
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "invalid sizes provided for Banner 0 x 90",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index 62b0b604..d266bc38 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -1266,7 +1266,7 @@ func TestBuildAmpObject(t *testing.T) {
 
 	for _, test := range testCases {
 		// Set up test, declare a new mock logger every time
-		actualAmpObject, endpoint := AmpObjectTestSetup(t, test.inTagId, test.inStoredRequest, false)
+		actualAmpObject, endpoint := ampObjectTestSetup(t, test.inTagId, test.inStoredRequest, false)
 		// Run test
 		endpoint(recorder, request, nil)
 
@@ -1332,13 +1332,13 @@ func TestIdGeneration(t *testing.T) {
 
 	for _, test := range testCases {
 		// Set up and run test
-		actualAmpObject, endpoint := AmpObjectTestSetup(t, "test", test.givenInStoredRequest, test.givenGenerateRequestID)
+		actualAmpObject, endpoint := ampObjectTestSetup(t, "test", test.givenInStoredRequest, test.givenGenerateRequestID)
 		endpoint(recorder, request, nil)
 		assert.Equalf(t, test.expectedID, actualAmpObject.Request.ID, "Bid Request ID is incorrect: %s\n", test.description)
 	}
 }
 
-func AmpObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMessage, generateRequestID bool) (*analytics.AmpObject, httprouter.Handle) {
+func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMessage, generateRequestID bool) (*analytics.AmpObject, httprouter.Handle) {
 	actualAmpObject := analytics.AmpObject{}
 	logger := newMockLogger(&actualAmpObject)
 
@@ -1363,3 +1363,65 @@ func AmpObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMe
 	)
 	return &actualAmpObject, endpoint
 }
+
+func TestAmpAuctionResponseHeaders(t *testing.T) {
+	testCases := []struct {
+		description         string
+		requestURLArguments string
+		expectedStatus      int
+		expectedHeaders     func(http.Header)
+	}{
+		{
+			description:         "Success Response",
+			requestURLArguments: "?tag_id=1&__amp_source_origin=foo",
+			expectedStatus:      200,
+			expectedHeaders: func(h http.Header) {
+				h.Set("AMP-Access-Control-Allow-Source-Origin", "foo")
+				h.Set("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin")
+				h.Set("X-Prebid", "pbs-go/unknown")
+				h.Set("Content-Type", "text/plain; charset=utf-8")
+			},
+		},
+		{
+			description:         "Failure Response",
+			requestURLArguments: "?tag_id=invalid&__amp_source_origin=foo",
+			expectedStatus:      400,
+			expectedHeaders: func(h http.Header) {
+				h.Set("AMP-Access-Control-Allow-Source-Origin", "foo")
+				h.Set("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin")
+				h.Set("X-Prebid", "pbs-go/unknown")
+			},
+		},
+	}
+
+	storedRequests := map[string]json.RawMessage{
+		"1": json.RawMessage(validRequest(t, "site.json")),
+	}
+	exchange := &nobidExchange{}
+	endpoint, _ := NewAmpEndpoint(
+		fakeUUIDGenerator{},
+		exchange,
+		newParamsValidator(t),
+		&mockAmpStoredReqFetcher{storedRequests},
+		empty_fetcher.EmptyFetcher{},
+		&config.Configuration{MaxRequestSize: maxSize},
+		&metricsConfig.NilMetricsEngine{},
+		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
+		map[string]string{},
+		[]byte{},
+		openrtb_ext.BuildBidderMap(),
+	)
+
+	for _, test := range testCases {
+		httpReq := httptest.NewRequest("GET", fmt.Sprintf("/openrtb2/auction/amp"+test.requestURLArguments), nil)
+		recorder := httptest.NewRecorder()
+
+		endpoint(recorder, httpReq, nil)
+
+		expectedHeaders := http.Header{}
+		test.expectedHeaders(expectedHeaders)
+
+		assert.Equal(t, test.expectedStatus, recorder.Result().StatusCode, test.description+":statuscode")
+		assert.Equal(t, expectedHeaders, recorder.Result().Header, test.description+":statuscode")
+	}
+}
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index c42580fc..9b2bf1dd 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -3577,6 +3577,61 @@ func TestValidateNativeAssetData(t *testing.T) {
 	}
 }
 
+func TestAuctionResponseHeaders(t *testing.T) {
+	testCases := []struct {
+		description     string
+		requestBody     string
+		expectedStatus  int
+		expectedHeaders func(http.Header)
+	}{
+		{
+			description:    "Success Response",
+			requestBody:    validRequest(t, "site.json"),
+			expectedStatus: 200,
+			expectedHeaders: func(h http.Header) {
+				h.Set("X-Prebid", "pbs-go/unknown")
+				h.Set("Content-Type", "application/json")
+			},
+		},
+		{
+			description:    "Failure Response",
+			requestBody:    "{}",
+			expectedStatus: 400,
+			expectedHeaders: func(h http.Header) {
+				h.Set("X-Prebid", "pbs-go/unknown")
+			},
+		},
+	}
+
+	exchange := &nobidExchange{}
+	endpoint, _ := NewEndpoint(
+		fakeUUIDGenerator{},
+		exchange,
+		newParamsValidator(t),
+		empty_fetcher.EmptyFetcher{},
+		empty_fetcher.EmptyFetcher{},
+		&config.Configuration{MaxRequestSize: maxSize},
+		&metricsConfig.NilMetricsEngine{},
+		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
+		map[string]string{},
+		[]byte{},
+		openrtb_ext.BuildBidderMap(),
+		empty_fetcher.EmptyFetcher{})
+
+	for _, test := range testCases {
+		httpReq := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(test.requestBody))
+		recorder := httptest.NewRecorder()
+
+		endpoint(recorder, httpReq, nil)
+
+		expectedHeaders := http.Header{}
+		test.expectedHeaders(expectedHeaders)
+
+		assert.Equal(t, test.expectedStatus, recorder.Result().StatusCode, test.description+":statuscode")
+		assert.Equal(t, expectedHeaders, recorder.Result().Header, test.description+":statuscode")
+	}
+}
+
 // warningsCheckExchange is a well-behaved exchange which stores all incoming warnings.
 type warningsCheckExchange struct {
 	auctionRequest exchange.AuctionRequest
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index 91512a2e..c4d8602a 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -1,7 +1,6 @@
 package openrtb2
 
 import (
-	"bytes"
 	"context"
 	"encoding/json"
 	"errors"
@@ -29,11 +28,7 @@ import (
 
 func TestVideoEndpointImpressionsNumber(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -62,16 +57,11 @@ func TestVideoEndpointImpressionsNumber(t *testing.T) {
 	assert.Len(t, resp.AdPods[4].Targeting, 3, "Incorrect Targeting data in response")
 
 	assert.Equal(t, resp.AdPods[4].Targeting[0].HbPbCatDur, "20.00_395_30s", "Incorrect number of Ad Pods in response")
-
 }
 
 func TestVideoEndpointImpressionsDuration(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_different_durations.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_different_durations.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -102,7 +92,6 @@ func TestVideoEndpointImpressionsDuration(t *testing.T) {
 	assert.Equal(t, ex.lastRequest.Imp[17].ID, "2_5", "Incorrect impression id in request")
 	assert.Equal(t, ex.lastRequest.Imp[17].Video.MaxDuration, int64(30), "Incorrect impression max duration in request")
 	assert.Equal(t, ex.lastRequest.Imp[17].Video.MinDuration, int64(30), "Incorrect impression min duration in request")
-
 }
 
 func TestCreateBidExtension(t *testing.T) {
@@ -143,7 +132,6 @@ func TestCreateBidExtension(t *testing.T) {
 	}
 	assert.Equal(t, resExt.Prebid.Targeting.DurationRangeSec, durationRange, "Duration range seconds is incorrect")
 	assert.Equal(t, resExt.Prebid.Targeting.PriceGranularity.Ranges, priceGranRanges, "Price granularity is incorrect")
-
 }
 
 func TestCreateBidExtensionExactDurTrueNoPriceRange(t *testing.T) {
@@ -183,11 +171,7 @@ func TestVideoEndpointDebugQueryTrue(t *testing.T) {
 	ex := &mockExchangeVideo{
 		cache: &mockCacheClient{},
 	}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video?debug=true", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -225,11 +209,7 @@ func TestVideoEndpointDebugQueryFalse(t *testing.T) {
 	ex := &mockExchangeVideo{
 		cache: &mockCacheClient{},
 	}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video?debug=123", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -267,11 +247,7 @@ func TestVideoEndpointDebugError(t *testing.T) {
 	ex := &mockExchangeVideo{
 		cache: &mockCacheClient{},
 	}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_invalid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_invalid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video?debug=true", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -289,11 +265,7 @@ func TestVideoEndpointDebugNoAdPods(t *testing.T) {
 	ex := &mockExchangeVideoNoBids{
 		cache: &mockCacheClient{},
 	}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video?debug=true", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -323,11 +295,7 @@ func TestVideoEndpointDebugNoAdPods(t *testing.T) {
 
 func TestVideoEndpointNoPods(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_invalid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_invalid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -877,11 +845,7 @@ func TestHandleError(t *testing.T) {
 
 func TestHandleErrorMetrics(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_invalid_sample.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_invalid_sample.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -899,87 +863,64 @@ func TestHandleErrorMetrics(t *testing.T) {
 
 func TestParseVideoRequestWithUserAgentAndHeader(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_with_device_user_agent.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_with_device_user_agent.json")
 	headers := http.Header{}
 	headers.Add("User-Agent", "TestHeader")
 
 	deps := mockDeps(t, ex)
-	reqBody := string(getRequestPayload(t, reqData))
 	req, valErr, podErr := deps.parseVideoRequest([]byte(reqBody), headers)
 
 	assert.Equal(t, "TestHeaderSample", req.Device.UA, "Header should be taken from original request")
 	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
 	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
-
 }
 
 func TestParseVideoRequestWithUserAgentAndEmptyHeader(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_with_device_user_agent.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_with_device_user_agent.json")
 
 	headers := http.Header{}
 
 	deps := mockDeps(t, ex)
-	reqBody := string(getRequestPayload(t, reqData))
 	req, valErr, podErr := deps.parseVideoRequest([]byte(reqBody), headers)
 
 	assert.Equal(t, "TestHeaderSample", req.Device.UA, "Header should be taken from original request")
 	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
 	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
-
 }
 
 func TestParseVideoRequestWithoutUserAgentWithHeader(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_without_device_user_agent.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_without_device_user_agent.json")
 	headers := http.Header{}
 	headers.Add("User-Agent", "TestHeader")
 
 	deps := mockDeps(t, ex)
-	reqBody := string(getRequestPayload(t, reqData))
 	req, valErr, podErr := deps.parseVideoRequest([]byte(reqBody), headers)
 
 	assert.Equal(t, "TestHeader", req.Device.UA, "Device.ua should be taken from request header")
 	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
 	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
-
 }
 
 func TestParseVideoRequestWithoutUserAgentAndEmptyHeader(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_without_device_user_agent.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_without_device_user_agent.json")
 
 	headers := http.Header{}
 
 	deps := mockDeps(t, ex)
-	reqBody := string(getRequestPayload(t, reqData))
+
 	req, valErr, podErr := deps.parseVideoRequest([]byte(reqBody), headers)
 
 	assert.Equal(t, "", req.Device.UA, "Device.ua should be empty")
 	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
 	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
-
 }
 
 func TestParseVideoRequestWithEncodedUserAgentInHeader(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_without_device_user_agent.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_without_device_user_agent.json")
 
 	uaEncoded := "Mozilla%2F5.0%20%28Macintosh%3B%20Intel%20Mac%20OS%20X%2010_14_6%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F78.0.3904.87%20Safari%2F537.36"
 	uaDecoded := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
@@ -988,21 +929,16 @@ func TestParseVideoRequestWithEncodedUserAgentInHeader(t *testing.T) {
 	headers.Add("User-Agent", uaEncoded)
 
 	deps := mockDeps(t, ex)
-	reqBody := string(getRequestPayload(t, reqData))
 	req, valErr, podErr := deps.parseVideoRequest([]byte(reqBody), headers)
 
 	assert.Equal(t, uaDecoded, req.Device.UA, "Device.ua should be taken from request header")
 	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
 	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
-
 }
 
 func TestParseVideoRequestWithDecodedUserAgentInHeader(t *testing.T) {
 	ex := &mockExchangeVideo{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_without_device_user_agent.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_without_device_user_agent.json")
 
 	uaDecoded := "Mozilla/5.0+(Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
 
@@ -1010,13 +946,11 @@ func TestParseVideoRequestWithDecodedUserAgentInHeader(t *testing.T) {
 	headers.Add("User-Agent", uaDecoded)
 
 	deps := mockDeps(t, ex)
-	reqBody := string(getRequestPayload(t, reqData))
 	req, valErr, podErr := deps.parseVideoRequest([]byte(reqBody), headers)
 
 	assert.Equal(t, uaDecoded, req.Device.UA, "Device.ua should be taken from request header")
 	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
 	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
-
 }
 
 func TestHandleErrorDebugLog(t *testing.T) {
@@ -1111,15 +1045,10 @@ func TestCCPA(t *testing.T) {
 	}
 
 	for _, test := range testCases {
-		// Load Test Request
-		requestContainerBytes, err := ioutil.ReadFile(test.testFilePath)
-		if err != nil {
-			t.Fatalf("%s: Failed to fetch a valid request: %v", test.description, err)
-		}
-		requestBytes := getRequestPayload(t, requestContainerBytes)
+		reqBody := readVideoTestFile(t, test.testFilePath)
 
 		// Create HTTP Request + Response Recorder
-		httpRequest := httptest.NewRequest("POST", "/openrtb2/video", bytes.NewReader(requestBytes))
+		httpRequest := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(reqBody))
 		httpResponseRecorder := httptest.NewRecorder()
 
 		// Run Test
@@ -1132,7 +1061,7 @@ func TestCCPA(t *testing.T) {
 			t.Fatalf("%s: The request never made it into the exchange.", test.description)
 		}
 		extRegs := &openrtb_ext.ExtRegs{}
-		if err = json.Unmarshal(ex.lastRequest.Regs.Ext, extRegs); err != nil {
+		if err := json.Unmarshal(ex.lastRequest.Regs.Ext, extRegs); err != nil {
 			t.Fatalf("%s: Failed to unmarshal reg.ext in request to the exchange: %v", test.description, err)
 		}
 		if test.expectConsentString {
@@ -1154,11 +1083,7 @@ func TestCCPA(t *testing.T) {
 
 func TestVideoEndpointAppendBidderNames(t *testing.T) {
 	ex := &mockExchangeAppendBidderNames{}
-	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_appendbiddernames.json")
-	if err != nil {
-		t.Fatalf("Failed to fetch a valid request: %v", err)
-	}
-	reqBody := string(getRequestPayload(t, reqData))
+	reqBody := readVideoTestFile(t, "sample-requests/video/video_valid_sample_appendbiddernames.json")
 	req := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(reqBody))
 	recorder := httptest.NewRecorder()
 
@@ -1191,7 +1116,6 @@ func TestVideoEndpointAppendBidderNames(t *testing.T) {
 	assert.Len(t, resp.AdPods[4].Targeting, 3, "Incorrect Targeting data in response")
 
 	assert.Equal(t, resp.AdPods[4].Targeting[0].HbPbCatDur, "20.00_395_30s_appnexus", "Incorrect number of Ad Pods in response")
-
 }
 
 func TestFormatTargetingKey(t *testing.T) {
@@ -1204,6 +1128,50 @@ func TestFormatTargetingKeyLongKey(t *testing.T) {
 	assert.Equal(t, "hb_pb_20.00", res, "Tergeting key constructed incorrectly")
 }
 
+func TestVideoAuctionResponseHeaders(t *testing.T) {
+	testCases := []struct {
+		description     string
+		givenTestFile   string
+		expectedStatus  int
+		expectedHeaders func(http.Header)
+	}{
+		{
+			description:    "Success Response",
+			givenTestFile:  "sample-requests/video/video_valid_sample.json",
+			expectedStatus: 200,
+			expectedHeaders: func(h http.Header) {
+				h.Set("X-Prebid", "pbs-go/unknown")
+				h.Set("Content-Type", "application/json")
+			},
+		}, {
+			description:    "Failure Response",
+			givenTestFile:  "sample-requests/video/video_invalid_sample.json",
+			expectedStatus: 500,
+			expectedHeaders: func(h http.Header) {
+				h.Set("X-Prebid", "pbs-go/unknown")
+			},
+		},
+	}
+
+	exchange := &mockExchangeVideo{}
+	endpoint := mockDeps(t, exchange)
+
+	for _, test := range testCases {
+		requestBody := readVideoTestFile(t, test.givenTestFile)
+
+		httpReq := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(requestBody))
+		recorder := httptest.NewRecorder()
+
+		endpoint.VideoAuctionEndpoint(recorder, httpReq, nil)
+
+		expectedHeaders := http.Header{}
+		test.expectedHeaders(expectedHeaders)
+
+		assert.Equal(t, test.expectedStatus, recorder.Result().StatusCode, test.description+":statuscode")
+		assert.Equal(t, expectedHeaders, recorder.Result().Header, test.description+":statuscode")
+	}
+}
+
 func mockDepsWithMetrics(t *testing.T, ex *mockExchangeVideo) (*endpointDeps, *metrics.Metrics, *mockAnalyticsModule) {
 	mockModule := &mockAnalyticsModule{}
 
@@ -1253,7 +1221,7 @@ func (m *mockAnalyticsModule) LogAmpObject(ao *analytics.AmpObject) { return }
 func (m *mockAnalyticsModule) LogNotificationEventObject(ne *analytics.NotificationEvent) { return }
 
 func mockDeps(t *testing.T, ex *mockExchangeVideo) *endpointDeps {
-	deps := &endpointDeps{
+	return &endpointDeps{
 		fakeUUIDGenerator{},
 		ex,
 		newParamsValidator(t),
@@ -1272,8 +1240,6 @@ func mockDeps(t *testing.T, ex *mockExchangeVideo) *endpointDeps {
 		hardcodedResponseIPValidator{response: true},
 		empty_fetcher.EmptyFetcher{},
 	}
-
-	return deps
 }
 
 func mockDepsAppendBidderNames(t *testing.T, ex *mockExchangeAppendBidderNames) *endpointDeps {
@@ -1443,3 +1409,12 @@ var testVideoStoredImpData = map[string]json.RawMessage{
 var testVideoStoredRequestData = map[string]json.RawMessage{
 	"80ce30c53c16e6ede735f123ef6e32361bfc7b22": json.RawMessage(`{"accountid": "11223344", "site": {"page": "mygame.foo.com"}}`),
 }
+
+func readVideoTestFile(t *testing.T, filename string) string {
+	requestData, err := ioutil.ReadFile(filename)
+	if err != nil {
+		t.Fatalf("Failed to fetch a valid request: %v", err)
+	}
+
+	return string(getRequestPayload(t, requestData))
+}
diff --git a/exchange/adapter_util_test.go b/exchange/adapter_util_test.go
index b3a05cdc..9f2c7b8f 100644
--- a/exchange/adapter_util_test.go
+++ b/exchange/adapter_util_test.go
@@ -238,6 +238,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 			bidderInfos: map[string]config.BidderInfo{},
 			expected: map[string]string{
 				"lifestreet": `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
+				"adagio":     `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 			},
 		},
 		{
@@ -245,6 +246,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 			bidderInfos: map[string]config.BidderInfo{"appnexus": infoEnabled},
 			expected: map[string]string{
 				"lifestreet": `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
+				"adagio":     `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 			},
 		},
 		{
@@ -252,6 +254,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 			bidderInfos: map[string]config.BidderInfo{"appnexus": infoDisabled},
 			expected: map[string]string{
 				"lifestreet": `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
+				"adagio":     `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 				"appnexus":   `Bidder "appnexus" has been disabled on this instance of Prebid Server. Please work with the PBS host to enable this bidder again.`,
 			},
 		},
@@ -260,6 +263,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 			bidderInfos: map[string]config.BidderInfo{"appnexus": infoDisabled, "openx": infoEnabled},
 			expected: map[string]string{
 				"lifestreet": `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
+				"adagio":     `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 				"appnexus":   `Bidder "appnexus" has been disabled on this instance of Prebid Server. Please work with the PBS host to enable this bidder again.`,
 			},
 		},
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index f67b6ffb..e250b65e 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -2513,120 +2513,6 @@ func TestRemoveUnpermissionedEidsEmptyValidations(t *testing.T) {
 	}
 }
 
-func TestBuildXPrebidHeader(t *testing.T) {
-	testCases := []struct {
-		description   string
-		version       string
-		requestExt    *openrtb_ext.ExtRequest
-		requestAppExt *openrtb_ext.ExtApp
-		result        string
-	}{
-		{
-			description: "No versions",
-			version:     "",
-			result:      "pbs-go/unknown",
-		},
-		{
-			description: "pbs",
-			version:     "test-version",
-			result:      "pbs-go/test-version",
-		},
-		{
-			description: "prebid.js",
-			version:     "test-version",
-			requestExt: &openrtb_ext.ExtRequest{
-				Prebid: openrtb_ext.ExtRequestPrebid{
-					Channel: &openrtb_ext.ExtRequestPrebidChannel{
-						Name:    "pbjs",
-						Version: "test-pbjs-version",
-					},
-				},
-			},
-			result: "pbs-go/test-version,pbjs/test-pbjs-version",
-		},
-		{
-			description: "unknown prebid.js",
-			version:     "test-version",
-			requestExt: &openrtb_ext.ExtRequest{
-				Prebid: openrtb_ext.ExtRequestPrebid{
-					Channel: &openrtb_ext.ExtRequestPrebidChannel{
-						Name: "pbjs",
-					},
-				},
-			},
-			result: "pbs-go/test-version,pbjs/unknown",
-		},
-		{
-			description: "channel without a name",
-			version:     "test-version",
-			requestExt: &openrtb_ext.ExtRequest{
-				Prebid: openrtb_ext.ExtRequestPrebid{
-					Channel: &openrtb_ext.ExtRequestPrebidChannel{
-						Version: "test-version",
-					},
-				},
-			},
-			result: "pbs-go/test-version",
-		},
-		{
-			description: "prebid-mobile",
-			version:     "test-version",
-			requestAppExt: &openrtb_ext.ExtApp{
-				Prebid: openrtb_ext.ExtAppPrebid{
-					Source:  "prebid-mobile",
-					Version: "test-prebid-mobile-version",
-				},
-			},
-			result: "pbs-go/test-version,prebid-mobile/test-prebid-mobile-version",
-		},
-		{
-			description: "app ext without a source",
-			version:     "test-version",
-			requestAppExt: &openrtb_ext.ExtApp{
-				Prebid: openrtb_ext.ExtAppPrebid{
-					Version: "test-version",
-				},
-			},
-			result: "pbs-go/test-version",
-		},
-		{
-			description: "Version found in both req.Ext and req.App.Ext",
-			version:     "test-version",
-			requestExt: &openrtb_ext.ExtRequest{
-				Prebid: openrtb_ext.ExtRequestPrebid{
-					Channel: &openrtb_ext.ExtRequestPrebidChannel{
-						Name:    "pbjs",
-						Version: "test-pbjs-version",
-					},
-				},
-			},
-			requestAppExt: &openrtb_ext.ExtApp{
-				Prebid: openrtb_ext.ExtAppPrebid{
-					Source:  "prebid-mobile",
-					Version: "test-prebid-mobile-version",
-				},
-			},
-			result: "pbs-go/test-version,pbjs/test-pbjs-version,prebid-mobile/test-prebid-mobile-version",
-		},
-	}
-
-	for _, test := range testCases {
-		req := &openrtb2.BidRequest{}
-		if test.requestExt != nil {
-			reqExt, err := json.Marshal(test.requestExt)
-			assert.NoError(t, err, test.description+":err marshalling reqExt")
-			req.Ext = reqExt
-		}
-		if test.requestAppExt != nil {
-			reqAppExt, err := json.Marshal(test.requestAppExt)
-			assert.NoError(t, err, test.description+":err marshalling reqAppExt")
-			req.App = &openrtb2.App{Ext: reqAppExt}
-		}
-		result := buildXPrebidHeader(req, test.version)
-		assert.Equal(t, test.result, result, test.description+":result")
-	}
-}
-
 func TestCleanOpenRTBRequestsSChainMultipleBidders(t *testing.T) {
 	req := &openrtb2.BidRequest{
 		Site: &openrtb2.Site{},
diff --git a/version/xprebidheader_test.go b/version/xprebidheader_test.go
new file mode 100644
index 00000000..1529a8f7
--- /dev/null
+++ b/version/xprebidheader_test.go
@@ -0,0 +1,149 @@
+package version
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/mxmCherry/openrtb/v15/openrtb2"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestBuildXPrebidHeader(t *testing.T) {
+	testCases := []struct {
+		description string
+		version     string
+		result      string
+	}{
+		{
+			description: "No Version",
+			version:     "",
+			result:      "pbs-go/unknown",
+		},
+		{
+			description: "Version",
+			version:     "0.100.0",
+			result:      "pbs-go/0.100.0",
+		},
+	}
+
+	for _, test := range testCases {
+		result := BuildXPrebidHeader(test.version)
+		assert.Equal(t, test.result, result, test.description)
+	}
+}
+
+func TestBuildXPrebidHeaderForRequest(t *testing.T) {
+	testCases := []struct {
+		description   string
+		version       string
+		requestExt    *openrtb_ext.ExtRequest
+		requestAppExt *openrtb_ext.ExtApp
+		result        string
+	}{
+		{
+			description: "No versions",
+			version:     "",
+			result:      "pbs-go/unknown",
+		},
+		{
+			description: "pbs",
+			version:     "test-version",
+			result:      "pbs-go/test-version",
+		},
+		{
+			description: "prebid.js",
+			version:     "test-version",
+			requestExt: &openrtb_ext.ExtRequest{
+				Prebid: openrtb_ext.ExtRequestPrebid{
+					Channel: &openrtb_ext.ExtRequestPrebidChannel{
+						Name:    "pbjs",
+						Version: "test-pbjs-version",
+					},
+				},
+			},
+			result: "pbs-go/test-version,pbjs/test-pbjs-version",
+		},
+		{
+			description: "unknown prebid.js",
+			version:     "test-version",
+			requestExt: &openrtb_ext.ExtRequest{
+				Prebid: openrtb_ext.ExtRequestPrebid{
+					Channel: &openrtb_ext.ExtRequestPrebidChannel{
+						Name: "pbjs",
+					},
+				},
+			},
+			result: "pbs-go/test-version,pbjs/unknown",
+		},
+		{
+			description: "channel without a name",
+			version:     "test-version",
+			requestExt: &openrtb_ext.ExtRequest{
+				Prebid: openrtb_ext.ExtRequestPrebid{
+					Channel: &openrtb_ext.ExtRequestPrebidChannel{
+						Version: "test-version",
+					},
+				},
+			},
+			result: "pbs-go/test-version",
+		},
+		{
+			description: "prebid-mobile",
+			version:     "test-version",
+			requestAppExt: &openrtb_ext.ExtApp{
+				Prebid: openrtb_ext.ExtAppPrebid{
+					Source:  "prebid-mobile",
+					Version: "test-prebid-mobile-version",
+				},
+			},
+			result: "pbs-go/test-version,prebid-mobile/test-prebid-mobile-version",
+		},
+		{
+			description: "app ext without a source",
+			version:     "test-version",
+			requestAppExt: &openrtb_ext.ExtApp{
+				Prebid: openrtb_ext.ExtAppPrebid{
+					Version: "test-version",
+				},
+			},
+			result: "pbs-go/test-version",
+		},
+		{
+			description: "Version found in both req.Ext and req.App.Ext",
+			version:     "test-version",
+			requestExt: &openrtb_ext.ExtRequest{
+				Prebid: openrtb_ext.ExtRequestPrebid{
+					Channel: &openrtb_ext.ExtRequestPrebidChannel{
+						Name:    "pbjs",
+						Version: "test-pbjs-version",
+					},
+				},
+			},
+			requestAppExt: &openrtb_ext.ExtApp{
+				Prebid: openrtb_ext.ExtAppPrebid{
+					Source:  "prebid-mobile",
+					Version: "test-prebid-mobile-version",
+				},
+			},
+			result: "pbs-go/test-version,pbjs/test-pbjs-version,prebid-mobile/test-prebid-mobile-version",
+		},
+	}
+
+	for _, test := range testCases {
+		req := &openrtb2.BidRequest{}
+		if test.requestExt != nil {
+			reqExt, err := json.Marshal(test.requestExt)
+			assert.NoError(t, err, test.description+":err marshalling reqExt")
+			req.Ext = reqExt
+		}
+		if test.requestAppExt != nil {
+			reqAppExt, err := json.Marshal(test.requestAppExt)
+			assert.NoError(t, err, test.description+":err marshalling reqAppExt")
+			req.App = &openrtb2.App{Ext: reqAppExt}
+		}
+		result := BuildXPrebidHeaderForRequest(req, test.version)
+		assert.Equal(t, test.result, result, test.description+":result")
+	}
+}