Repository: prebid/prebid-server
Pull request #1909 (2021-06-29 20:03:48)

Rubicon: Update segtax logic


Patch:
diff --git a/adapters/bidder.go b/adapters/bidder.go
index 2e5ec83c..b7bde4bc 100644
--- a/adapters/bidder.go
+++ b/adapters/bidder.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/mxmCherry/openrtb/v15/openrtb2"
 	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/currency"
 	"github.com/prebid/prebid-server/metrics"
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
@@ -138,6 +139,25 @@ func (r *RequestData) SetBasicAuth(username string, password string) {
 type ExtraRequestInfo struct {
 	PbsEntryPoint              metrics.RequestType
 	GlobalPrivacyControlHeader string
+	currencyConversions        currency.Conversions
+}
+
+func NewExtraRequestInfo(c currency.Conversions) ExtraRequestInfo {
+	return ExtraRequestInfo{
+		currencyConversions: c,
+	}
+}
+
+// ConvertCurrency converts a given amount from one currency to another, or returns:
+//  - Error if the `from` or `to` arguments are malformed or unknown ISO-4217 codes.
+//  - ConversionNotFoundError if the conversion mapping is unknown to Prebid Server
+//    and not provided in the bid request.
+func (r ExtraRequestInfo) ConvertCurrency(value float64, from, to string) (float64, error) {
+	if rate, err := r.currencyConversions.GetRate(from, to); err == nil {
+		return value * rate, nil
+	} else {
+		return 0, err
+	}
 }
 
 type Builder func(openrtb_ext.BidderName, config.Adapter) (Bidder, error)
diff --git a/adapters/bidmyadz/bidmyadz.go b/adapters/bidmyadz/bidmyadz.go
new file mode 100644
index 00000000..829d57e6
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadz.go
@@ -0,0 +1,157 @@
+package bidmyadz
+
+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
+}
+
+type bidExt struct {
+	MediaType string `json:"mediaType"`
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(
+	openRTBRequest *openrtb2.BidRequest,
+	reqInfo *adapters.ExtraRequestInfo,
+) (
+	requestsToBidder []*adapters.RequestData,
+	errs []error,
+) {
+
+	var errors []error
+
+	if len(openRTBRequest.Imp) > 1 {
+		errors = append(errors, &errortypes.BadInput{
+			Message: "Bidder does not support multi impression",
+		})
+	}
+
+	if openRTBRequest.Device.IP == "" && openRTBRequest.Device.IPv6 == "" {
+		errors = append(errors, &errortypes.BadInput{
+			Message: "IP/IPv6 is a required field",
+		})
+	}
+
+	if openRTBRequest.Device.UA == "" {
+		errors = append(errors, &errortypes.BadInput{
+			Message: "User-Agent is a required field",
+		})
+	}
+
+	if len(errors) != 0 {
+		return nil, errors
+	}
+
+	reqJSON, err := json.Marshal(openRTBRequest)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("X-Openrtb-Version", "2.5")
+
+	return []*adapters.RequestData{{
+		Method:  http.MethodPost,
+		Body:    reqJSON,
+		Uri:     a.endpoint,
+		Headers: headers,
+	}}, nil
+}
+
+func (a *adapter) MakeBids(
+	openRTBRequest *openrtb2.BidRequest,
+	requestToBidder *adapters.RequestData,
+	bidderRawResponse *adapters.ResponseData,
+) (
+	bidderResponse *adapters.BidderResponse,
+	errs []error,
+) {
+	if bidderRawResponse.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if bidderRawResponse.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Bad Request. %s", string(bidderRawResponse.Body)),
+		}}
+	}
+
+	if bidderRawResponse.StatusCode == http.StatusServiceUnavailable {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Bidder is unavailable. Please contact your account manager.",
+		}}
+	}
+
+	if bidderRawResponse.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Something went wrong. Status Code: [ %d ] %s", bidderRawResponse.StatusCode, string(bidderRawResponse.Body)),
+		}}
+	}
+
+	responseBody := bidderRawResponse.Body
+	var bidResp openrtb2.BidResponse
+	if err := json.Unmarshal(responseBody, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	if len(bidResp.SeatBid) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid",
+		}}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+
+	bids := bidResp.SeatBid[0].Bid
+
+	if len(bids) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid.Bids",
+		}}
+	}
+
+	bid := bids[0]
+
+	var bidExt bidExt
+	var bidType openrtb_ext.BidType
+
+	if err := json.Unmarshal(bid.Ext, &bidExt); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("BidExt parsing error. %s", err.Error()),
+		}}
+	}
+
+	bidType, err := getBidType(bidExt)
+
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+		Bid:     &bid,
+		BidType: bidType,
+	})
+	return bidResponse, nil
+}
+
+func getBidType(ext bidExt) (openrtb_ext.BidType, error) {
+	return openrtb_ext.ParseBidType(ext.MediaType)
+}
diff --git a/adapters/bidmyadz/usersync.go b/adapters/bidmyadz/usersync.go
new file mode 100644
index 00000000..755a184d
--- /dev/null
+++ b/adapters/bidmyadz/usersync.go
@@ -0,0 +1,12 @@
+package bidmyadz
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewBidmyadzSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("bidmyadz", temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/dmx/dmx.go b/adapters/dmx/dmx.go
index 7124d229..adcec4a3 100644
--- a/adapters/dmx/dmx.go
+++ b/adapters/dmx/dmx.go
@@ -148,7 +148,7 @@ func (adapter *DmxAdapter) MakeRequests(request *openrtb2.BidRequest, req *adapt
 		}
 		if dmxReq.User.Ext != nil {
 			if err := json.Unmarshal(dmxReq.User.Ext, &userExt); err == nil {
-				if len(userExt.Eids) > 0 || (userExt.DigiTrust != nil && userExt.DigiTrust.ID != "") {
+				if len(userExt.Eids) > 0 {
 					anyHasId = true
 				}
 			}
diff --git a/adapters/inmobi/usersync.go b/adapters/inmobi/usersync.go
new file mode 100644
index 00000000..7f022e3c
--- /dev/null
+++ b/adapters/inmobi/usersync.go
@@ -0,0 +1,12 @@
+package inmobi
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewInmobiSyncer(template *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("inmobi", template, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/ix/ix.go b/adapters/ix/ix.go
index 5e10138f..b251ec0f 100644
--- a/adapters/ix/ix.go
+++ b/adapters/ix/ix.go
@@ -7,7 +7,10 @@ import (
 	"fmt"
 	"io/ioutil"
 	"net/http"
+	"sort"
 
+	"github.com/mxmCherry/openrtb/v15/native1"
+	native1response "github.com/mxmCherry/openrtb/v15/native1/response"
 	"github.com/mxmCherry/openrtb/v15/openrtb2"
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/config"
@@ -400,7 +403,7 @@ func (a *IxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReque
 		for _, bid := range seatBid.Bid {
 			bidType, ok := impMediaType[bid.ImpID]
 			if !ok {
-				errs = append(errs, fmt.Errorf("Unmatched impression id: %s.", bid.ImpID))
+				errs = append(errs, fmt.Errorf("unmatched impression id: %s", bid.ImpID))
 			}
 
 			var bidExtVideo *openrtb_ext.ExtBidPrebidVideo
@@ -417,6 +420,28 @@ func (a *IxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReque
 				}
 			}
 
+			var bidNative1v1 *Native11Wrapper
+			if bidType == openrtb_ext.BidTypeNative {
+				err := json.Unmarshal([]byte(bid.AdM), &bidNative1v1)
+				if err == nil && len(bidNative1v1.Native.EventTrackers) > 0 {
+					mergeNativeImpTrackers(&bidNative1v1.Native)
+					if json, err := json.Marshal(bidNative1v1); err == nil {
+						bid.AdM = string(json)
+					}
+				}
+			}
+
+			var bidNative1v2 *native1response.Response
+			if bidType == openrtb_ext.BidTypeNative {
+				err := json.Unmarshal([]byte(bid.AdM), &bidNative1v2)
+				if err == nil && len(bidNative1v2.EventTrackers) > 0 {
+					mergeNativeImpTrackers(bidNative1v2)
+					if json, err := json.Marshal(bidNative1v2); err == nil {
+						bid.AdM = string(json)
+					}
+				}
+			}
+
 			bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{
 				Bid:      &bid,
 				BidType:  bidType,
@@ -444,3 +469,33 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters
 	}
 	return bidder, nil
 }
+
+// native 1.2 to 1.1 tracker compatibility handling
+
+type Native11Wrapper struct {
+	Native native1response.Response `json:"native,omitempty"`
+}
+
+func mergeNativeImpTrackers(bidNative *native1response.Response) {
+
+	// create unique list of imp pixels urls from `imptrackers` and `eventtrackers`
+	uniqueImpPixels := map[string]struct{}{}
+	for _, v := range bidNative.ImpTrackers {
+		uniqueImpPixels[v] = struct{}{}
+	}
+
+	for _, v := range bidNative.EventTrackers {
+		if v.Event == native1.EventTypeImpression && v.Method == native1.EventTrackingMethodImage {
+			uniqueImpPixels[v.URL] = struct{}{}
+		}
+	}
+
+	// rewrite `imptrackers` with new deduped list of imp pixels
+	bidNative.ImpTrackers = make([]string, 0)
+	for k := range uniqueImpPixels {
+		bidNative.ImpTrackers = append(bidNative.ImpTrackers, k)
+	}
+
+	// sort so tests pass correctly
+	sort.Strings(bidNative.ImpTrackers)
+}
diff --git a/adapters/rubicon/rubicon.go b/adapters/rubicon/rubicon.go
index 73f6a5d3..579af983 100644
--- a/adapters/rubicon/rubicon.go
+++ b/adapters/rubicon/rubicon.go
@@ -91,21 +91,21 @@ type rubiconExtUserTpID struct {
 	UID    string `json:"uid"`
 }
 
-type rubiconUserDataExt struct {
-	TaxonomyName string `json:"taxonomyname"`
+type rubiconDataExt struct {
+	SegTax int `json:"segtax"`
 }
 
 type rubiconUserExt struct {
-	Consent     string                        `json:"consent,omitempty"`
-	DigiTrust   *openrtb_ext.ExtUserDigiTrust `json:"digitrust"`
-	Eids        []openrtb_ext.ExtUserEid      `json:"eids,omitempty"`
-	TpID        []rubiconExtUserTpID          `json:"tpid,omitempty"`
-	RP          rubiconUserExtRP              `json:"rp"`
-	LiverampIdl string                        `json:"liveramp_idl,omitempty"`
+	Consent     string                   `json:"consent,omitempty"`
+	Eids        []openrtb_ext.ExtUserEid `json:"eids,omitempty"`
+	TpID        []rubiconExtUserTpID     `json:"tpid,omitempty"`
+	RP          rubiconUserExtRP         `json:"rp"`
+	LiverampIdl string                   `json:"liveramp_idl,omitempty"`
 }
 
 type rubiconSiteExtRP struct {
-	SiteID int `json:"site_id"`
+	SiteID int             `json:"site_id"`
+	Target json.RawMessage `json:"target,omitempty"`
 }
 
 type rubiconSiteExt struct {
@@ -756,12 +756,13 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 
 		if request.User != nil {
 			userCopy := *request.User
-			userExtRP := rubiconUserExt{RP: rubiconUserExtRP{Target: rubiconExt.Visitor}}
 
-			if err := updateUserExtWithIabAttribute(&userExtRP, userCopy.Data); err != nil {
+			target, err := updateExtWithIabAttribute(rubiconExt.Visitor, userCopy.Data, []int{4})
+			if err != nil {
 				errs = append(errs, err)
 				continue
 			}
+			userExtRP := rubiconUserExt{RP: rubiconUserExtRP{Target: target}}
 
 			if request.User.Ext != nil {
 				var userExt *openrtb_ext.ExtUser
@@ -772,9 +773,6 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 					continue
 				}
 				userExtRP.Consent = userExt.Consent
-				if userExt.DigiTrust != nil {
-					userExtRP.DigiTrust = userExt.DigiTrust
-				}
 				userExtRP.Eids = userExt.Eids
 
 				// set user.ext.tpid
@@ -849,19 +847,30 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 			thisImp.Video = nil
 		}
 
-		siteExt := rubiconSiteExt{RP: rubiconSiteExtRP{SiteID: rubiconExt.SiteId}}
 		pubExt := rubiconPubExt{RP: rubiconPubExtRP{AccountID: rubiconExt.AccountId}}
 
 		if request.Site != nil {
 			siteCopy := *request.Site
-			siteCopy.Ext, err = json.Marshal(&siteExt)
+			siteExtRP := rubiconSiteExt{RP: rubiconSiteExtRP{SiteID: rubiconExt.SiteId}}
+			target, err := updateExtWithIabAttribute(nil, siteCopy.Content.Data, []int{1, 2})
+			if err != nil {
+				errs = append(errs, err)
+				continue
+			}
+			siteExtRP.RP.Target = target
+
+			siteCopy.Ext, err = json.Marshal(&siteExtRP)
+			if err != nil {
+				errs = append(errs, err)
+				continue
+			}
+
 			siteCopy.Publisher = &openrtb2.Publisher{}
 			siteCopy.Publisher.Ext, err = json.Marshal(&pubExt)
 			rubiconRequest.Site = &siteCopy
-		}
-		if request.App != nil {
+		} else {
 			appCopy := *request.App
-			appCopy.Ext, err = json.Marshal(&siteExt)
+			appCopy.Ext, err = json.Marshal(rubiconSiteExt{RP: rubiconSiteExtRP{SiteID: rubiconExt.SiteId}})
 			appCopy.Publisher = &openrtb2.Publisher{}
 			appCopy.Publisher.Ext, err = json.Marshal(&pubExt)
 			rubiconRequest.App = &appCopy
@@ -908,41 +917,53 @@ func resolveBidFloorAttributes(bidFloor float64, bidFloorCur string) (float64, s
 	return bidFloor, bidFloorCur
 }
 
-func updateUserExtWithIabAttribute(userExtRP *rubiconUserExt, data []openrtb2.Data) error {
+func updateExtWithIabAttribute(target json.RawMessage, data []openrtb2.Data, segTaxes []int) (json.RawMessage, error) {
+	var segmentIdsToCopy = getSegmentIdsToCopy(data, segTaxes)
+
+	extRPTarget := make(map[string]interface{})
+
+	if target != nil {
+		if err := json.Unmarshal(target, &extRPTarget); err != nil {
+			return nil, &errortypes.BadInput{Message: err.Error()}
+		}
+	}
+
+	extRPTarget["iab"] = segmentIdsToCopy
+
+	jsonTarget, err := json.Marshal(&extRPTarget)
+	if err != nil {
+		return nil, &errortypes.BadInput{Message: err.Error()}
+	}
+	return jsonTarget, nil
+}
+
+func getSegmentIdsToCopy(data []openrtb2.Data, segTaxValues []int) []string {
 	var segmentIdsToCopy = make([]string, 0)
 
 	for _, dataRecord := range data {
 		if dataRecord.Ext != nil {
-			var dataExtObject rubiconUserDataExt
+			var dataExtObject rubiconDataExt
 			err := json.Unmarshal(dataRecord.Ext, &dataExtObject)
 			if err != nil {
 				continue
 			}
-			if strings.EqualFold(dataExtObject.TaxonomyName, "iab") {
+			if contains(segTaxValues, dataExtObject.SegTax) {
 				for _, segment := range dataRecord.Segment {
 					segmentIdsToCopy = append(segmentIdsToCopy, segment.ID)
 				}
 			}
 		}
 	}
+	return segmentIdsToCopy
+}
 
-	userExtRPTarget := make(map[string]interface{})
-
-	if userExtRP.RP.Target != nil {
-		if err := json.Unmarshal(userExtRP.RP.Target, &userExtRPTarget); err != nil {
-			return &errortypes.BadInput{Message: err.Error()}
+func contains(s []int, e int) bool {
+	for _, a := range s {
+		if a == e {
+			return true
 		}
 	}
-
-	userExtRPTarget["iab"] = segmentIdsToCopy
-
-	if target, err := json.Marshal(&userExtRPTarget); err != nil {
-		return &errortypes.BadInput{Message: err.Error()}
-	} else {
-		userExtRP.RP.Target = target
-	}
-
-	return nil
+	return false
 }
 
 func getTpIdsAndSegments(eids []openrtb_ext.ExtUserEid) (mappedRubiconUidsParam, []error) {
diff --git a/adapters/sa_lunamedia/salunamedia.go b/adapters/sa_lunamedia/salunamedia.go
new file mode 100644
index 00000000..ea6e12b0
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamedia.go
@@ -0,0 +1,132 @@
+package salunamedia
+
+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
+}
+
+type bidExt struct {
+	MediaType string `json:"mediaType"`
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(
+	openRTBRequest *openrtb2.BidRequest,
+	reqInfo *adapters.ExtraRequestInfo,
+) (
+	requestsToBidder []*adapters.RequestData,
+	errs []error,
+) {
+
+	reqJSON, err := json.Marshal(openRTBRequest)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+
+	return []*adapters.RequestData{{
+		Method:  http.MethodPost,
+		Body:    reqJSON,
+		Uri:     a.endpoint,
+		Headers: headers,
+	}}, nil
+}
+
+func (a *adapter) MakeBids(
+	openRTBRequest *openrtb2.BidRequest,
+	requestToBidder *adapters.RequestData,
+	bidderRawResponse *adapters.ResponseData,
+) (
+	bidderResponse *adapters.BidderResponse,
+	errs []error,
+) {
+	if bidderRawResponse.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if bidderRawResponse.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Bad Request. %s", string(bidderRawResponse.Body)),
+		}}
+	}
+
+	if bidderRawResponse.StatusCode == http.StatusServiceUnavailable {
+		return nil, []error{&errortypes.BadInput{
+			Message: "Bidder unavailable. Please contact the bidder support.",
+		}}
+	}
+
+	if bidderRawResponse.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Status Code: [ %d ] %s", bidderRawResponse.StatusCode, string(bidderRawResponse.Body)),
+		}}
+	}
+
+	responseBody := bidderRawResponse.Body
+	var bidResp openrtb2.BidResponse
+	if err := json.Unmarshal(responseBody, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	if len(bidResp.SeatBid) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid",
+		}}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+
+	bids := bidResp.SeatBid[0].Bid
+
+	if len(bids) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid.Bids",
+		}}
+	}
+
+	bid := bids[0]
+
+	var bidExt bidExt
+	var bidType openrtb_ext.BidType
+
+	if err := json.Unmarshal(bid.Ext, &bidExt); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Missing BidExt",
+		}}
+	}
+
+	bidType, err := getBidType(bidExt)
+
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+		Bid:     &bid,
+		BidType: bidType,
+	})
+	return bidResponse, nil
+}
+
+func getBidType(ext bidExt) (openrtb_ext.BidType, error) {
+	return openrtb_ext.ParseBidType(ext.MediaType)
+}
diff --git a/adapters/sa_lunamedia/usersync.go b/adapters/sa_lunamedia/usersync.go
new file mode 100644
index 00000000..f78b7944
--- /dev/null
+++ b/adapters/sa_lunamedia/usersync.go
@@ -0,0 +1,12 @@
+package salunamedia
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewSaLunamediaSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("salunamedia", temp, adapters.SyncTypeRedirect)
+}
diff --git a/config/config.go b/config/config.go
index 58bb40a5..34d941bc 100644
--- a/config/config.go
+++ b/config/config.go
@@ -587,6 +587,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAvocet, "https://ads.avct.cloud/getuid?&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Davocet%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7BUUID%7D%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBeachfront, "https://sync.bfmio.com/sync_s2s?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBeintoo, "https://ib.beintoo.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbeintoo%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBidmyadz, "https://cookie-sync.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ccpa={{.USPrivacy}}&red="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbidmyadz%26uid%3D%5BUID%5D%26us_privacy%3D{{.USPrivacy}}%26gdpr_consent%3D{{.GDPRConsent}}%26gdpr%3D{{.GDPR}}")
 	// openrtb_ext.BidderBidsCube doesn't have a good default.
 	// openrtb_ext.BidderBmtm doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBrightroll, "https://pr-bh.ybp.yahoo.com/sync/appnexusprebidserver/?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
@@ -610,6 +611,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGrid, "https://x.bidswitch.net/check_uuid/"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgrid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BBSW_UUID%7D?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGumGum, "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderImprovedigital, "https://ad.360yield.com/server_match?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BPUB_USER_ID%7D")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderInMobi, "https://id5-sync.com/i/495/0.gif?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&callback="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dinmobi%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BID5UID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderIx, "https://ssum.casalemedia.com/usermatchredir?s=194962&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dix%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	// openrtb_ext.BidderInvibes doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderJixie, "https://id.jixie.io/api/sync?pid=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Djixie%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25JXUID%25%25")
@@ -617,6 +619,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderLockerDome, "https://lockerdome.com/usync/prebidserver?pid="+cfg.Adapters["lockerdome"].PlatformID+"&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7Buid%7D%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderLogicad, "https://cr-p31.ladsp.jp/cookiesender/31?r=true&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ru="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dlogicad%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderLunaMedia, "https://api.lunamedia.io/xp/user-sync?redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dlunamedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSaLunaMedia, "https://cookie.lmgssp.com/pserver?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ccpa={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsa_lunamedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BUID%5D")
 	// openrtb_ext.BidderMadvertise doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMarsmedia, "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")
 	// openrtb_ext.BidderMediafuse doesn't have a good default.
@@ -842,6 +845,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.beintoo.endpoint", "https://ib.beintoo.com/um")
 	v.SetDefault("adapters.between.endpoint", "http://{{.Host}}.betweendigital.com/openrtb_bid?sspId={{.PublisherID}}")
 	v.SetDefault("adapters.bidmachine.endpoint", "https://{{.Host}}.bidmachine.io")
+	v.SetDefault("adapters.bidmyadz.endpoint", "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc")
 	v.SetDefault("adapters.bidscube.endpoint", "http://supply.bidscube.com/?c=o&m=rtb")
 	v.SetDefault("adapters.bmtm.endpoint", "https://one.elitebidder.com/api/pbs")
 	v.SetDefault("adapters.brightroll.endpoint", "http://east-bid.ybp.yahoo.com/bid/appnexuspbs")
@@ -878,6 +882,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.lockerdome.endpoint", "https://lockerdome.com/ladbid/prebidserver/openrtb2")
 	v.SetDefault("adapters.logicad.endpoint", "https://pbs.ladsp.com/adrequest/prebidserver")
 	v.SetDefault("adapters.lunamedia.endpoint", "http://api.lunamedia.io/xp/get?pubid={{.PublisherID}}")
+	v.SetDefault("adapters.sa_lunamedia.endpoint", "http://balancer.lmgssp.com/pserver")
 	v.SetDefault("adapters.madvertise.endpoint", "https://mobile.mng-ads.com/bidrequest{{.ZoneID}}")
 	v.SetDefault("adapters.marsmedia.endpoint", "https://bid306.rtbsrv.com/bidder/?bid=f3xtet")
 	v.SetDefault("adapters.mediafuse.endpoint", "http://ghb.hbmp.mediafuse.com/pbs/ortb")
diff --git a/currency/aggregate_conversions.go b/currency/aggregate_conversions.go
index 53c5ebff..a15404fe 100644
--- a/currency/aggregate_conversions.go
+++ b/currency/aggregate_conversions.go
@@ -23,7 +23,7 @@ func (re *AggregateConversions) GetRate(from string, to string) (float64, error)
 	rate, err := re.customRates.GetRate(from, to)
 	if err == nil {
 		return rate, nil
-	} else if _, isMissingRateErr := err.(ConversionRateNotFound); !isMissingRateErr {
+	} else if _, isMissingRateErr := err.(ConversionNotFoundError); !isMissingRateErr {
 		// other error, return the error
 		return 0, err
 	}
diff --git a/currency/constant_rates.go b/currency/constant_rates.go
index dde317d8..ccc5c24d 100644
--- a/currency/constant_rates.go
+++ b/currency/constant_rates.go
@@ -27,7 +27,7 @@ func (r *ConstantRates) GetRate(from string, to string) (float64, error) {
 	}
 
 	if fromUnit.String() != toUnit.String() {
-		return 0, ConversionRateNotFound{fromUnit.String(), toUnit.String()}
+		return 0, ConversionNotFoundError{FromCur: fromUnit.String(), ToCur: toUnit.String()}
 	}
 
 	return 1, nil
diff --git a/currency/errors.go b/currency/errors.go
index d764c15b..bb4c42aa 100644
--- a/currency/errors.go
+++ b/currency/errors.go
@@ -2,12 +2,12 @@ package currency
 
 import "fmt"
 
-// ConversionRateNotFound is thrown by the currency.Conversions GetRate(from string, to string) method
+// ConversionNotFoundError is thrown by the currency.Conversions GetRate(from string, to string) method
 // when the conversion rate between the two currencies, nor its reciprocal, can be found.
-type ConversionRateNotFound struct {
+type ConversionNotFoundError struct {
 	FromCur, ToCur string
 }
 
-func (err ConversionRateNotFound) Error() string {
+func (err ConversionNotFoundError) Error() string {
 	return fmt.Sprintf("Currency conversion rate not found: '%s' => '%s'", err.FromCur, err.ToCur)
 }
diff --git a/currency/rates.go b/currency/rates.go
index 62914c4b..b9cb0201 100644
--- a/currency/rates.go
+++ b/currency/rates.go
@@ -47,9 +47,9 @@ func (r *Rates) UnmarshalJSON(b []byte) error {
 // GetRate returns the conversion rate between two currencies or:
 //  - An error if one of the currency strings is not well-formed
 //  - An error if any of the currency strings is not a recognized currency code.
-//  - A MissingConversionRate error in case the conversion rate between the two
+//  - A ConversionNotFoundError in case the conversion rate between the two
 //    given currencies is not in the currencies rates map
-func (r *Rates) GetRate(from string, to string) (float64, error) {
+func (r *Rates) GetRate(from, to string) (float64, error) {
 	var err error
 	fromUnit, err := currency.ParseISO(from)
 	if err != nil {
@@ -70,7 +70,7 @@ func (r *Rates) GetRate(from string, to string) (float64, error) {
 			// In case we have an entry TO -> FROM
 			return 1 / conversion, nil
 		}
-		return 0, ConversionRateNotFound{fromUnit.String(), toUnit.String()}
+		return 0, ConversionNotFoundError{FromCur: fromUnit.String(), ToCur: toUnit.String()}
 	}
 	return 0, errors.New("rates are nil")
 }
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index d8a7fa68..c9f2bbdb 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -1124,13 +1124,9 @@ func (deps *endpointDeps) validateUser(user *openrtb2.User, aliases map[string]s
 	}
 
 	if user.Ext != nil {
-		// Creating ExtUser object to check if DigiTrust is valid
+		// Creating ExtUser object
 		var userExt openrtb_ext.ExtUser
 		if err := json.Unmarshal(user.Ext, &userExt); err == nil {
-			if userExt.DigiTrust != nil && userExt.DigiTrust.Pref != 0 {
-				// DigiTrust is not valid. Return error.
-				return errors.New("request.user contains a digitrust object that is not valid.")
-			}
 			// Check if the buyeruids are valid
 			if userExt.Prebid != nil {
 				if len(userExt.Prebid.BuyerUIDs) < 1 {
diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json b/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json
deleted file mode 100644
index 1fb7169f..00000000
--- a/endpoints/openrtb2/sample-requests/invalid-whole/digitrust.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "description": "Invalid digitrust object in user extension",
-  "mockBidRequest": {
-    "id": "request-with-invalid-digitrust-obj",
-    "site": {
-      "page": "test.somepage.com"
-    },
-    "imp": [
-      {
-        "id": "my-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "pmp": {
-          "deals": [
-            {
-              "id": "some-deal-id"
-            }
-          ]
-        },
-        "ext": {
-          "appnexus": {
-            "placementId": 12883451
-          }
-        }
-      }
-    ],
-    "user": {
-      "yob": 1989,
-      "ext": {
-        "digitrust": {
-          "id": "sample-digitrust-id",
-          "keyv": 1,
-          "pref": 1
-        }
-      }
-    }
-  },
-  "expectedReturnCode": 400,
-  "expectedErrorMessage": "Invalid request: request.user contains a digitrust object that is not valid.\n"
-}
diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json
deleted file mode 100644
index 5cd07074..00000000
--- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/digitrust.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "description": "Well formed amp request with digitrust extension that should run properly",
-  "mockBidRequest": {
-    "id": "request-with-valid-digitrust-obj",
-    "site": {
-      "page": "test.somepage.com"
-    },
-    "imp": [
-      {
-        "id": "my-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "pmp": {
-          "deals": [
-            {
-              "id": "some-deal-id"
-            }
-          ]
-        },
-        "ext": {
-          "appnexus": {
-            "placementId": 12883451
-          }
-        }
-      }
-    ],
-    "user": {
-      "yob": 1989,
-      "ext": {
-        "digitrust": {
-          "id": "sample-digitrust-id",
-          "keyv": 1,
-          "pref": 0
-        }
-      }
-    }
-  },
-  "expectedBidResponse": {
-      "id":"request-with-valid-digitrust-obj",
-      "bidid":"test bid id",
-      "nbr":0
-  },
-  "expectedReturnCode": 200
-}
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 1fdb7c24..17e0d4f5 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -33,6 +33,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/beintoo"
 	"github.com/prebid/prebid-server/adapters/between"
 	"github.com/prebid/prebid-server/adapters/bidmachine"
+	"github.com/prebid/prebid-server/adapters/bidmyadz"
 	"github.com/prebid/prebid-server/adapters/bidscube"
 	"github.com/prebid/prebid-server/adapters/bmtm"
 	"github.com/prebid/prebid-server/adapters/brightroll"
@@ -88,6 +89,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/rhythmone"
 	"github.com/prebid/prebid-server/adapters/rtbhouse"
 	"github.com/prebid/prebid-server/adapters/rubicon"
+	"github.com/prebid/prebid-server/adapters/sa_lunamedia"
 	"github.com/prebid/prebid-server/adapters/sharethrough"
 	"github.com/prebid/prebid-server/adapters/silvermob"
 	"github.com/prebid/prebid-server/adapters/smaato"
@@ -154,6 +156,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderBeintoo:           beintoo.Builder,
 		openrtb_ext.BidderBetween:           between.Builder,
 		openrtb_ext.BidderBidmachine:        bidmachine.Builder,
+		openrtb_ext.BidderBidmyadz:          bidmyadz.Builder,
 		openrtb_ext.BidderBidsCube:          bidscube.Builder,
 		openrtb_ext.BidderBmtm:              bmtm.Builder,
 		openrtb_ext.BidderBrightroll:        brightroll.Builder,
@@ -189,6 +192,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderLockerDome:        lockerdome.Builder,
 		openrtb_ext.BidderLogicad:           logicad.Builder,
 		openrtb_ext.BidderLunaMedia:         lunamedia.Builder,
+		openrtb_ext.BidderSaLunaMedia:       salunamedia.Builder,
 		openrtb_ext.BidderMadvertise:        madvertise.Builder,
 		openrtb_ext.BidderMarsmedia:         marsmedia.Builder,
 		openrtb_ext.BidderMediafuse:         adtelligent.Builder,
diff --git a/exchange/exchange.go b/exchange/exchange.go
index e96aadbc..6aaafcd1 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -449,7 +449,7 @@ func (e *exchange) getAllBids(
 			if givenAdjustment, ok := bidAdjustments[string(bidderRequest.BidderName)]; ok {
 				adjustmentFactor = givenAdjustment
 			}
-			var reqInfo adapters.ExtraRequestInfo
+			reqInfo := adapters.NewExtraRequestInfo(conversions)
 			reqInfo.PbsEntryPoint = bidderRequest.BidderLabels.RType
 			reqInfo.GlobalPrivacyControlHeader = globalPrivacyControlHeader
 			bids, err := e.adapterMap[bidderRequest.BidderCoreName].requestBid(ctx, bidderRequest.BidRequest, bidderRequest.BidderName, adjustmentFactor, conversions, &reqInfo, accountDebugAllowed, headerDebugAllowed)
diff --git a/exchange/utils.go b/exchange/utils.go
index 3def0425..0befeacd 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -332,7 +332,7 @@ func extractBuyerUIDs(user *openrtb2.User) (map[string]string, error) {
 	userExt.Prebid = nil
 
 	// Remarshal (instead of removing) if the ext has other known fields
-	if userExt.Consent != "" || userExt.DigiTrust != nil || len(userExt.Eids) > 0 {
+	if userExt.Consent != "" || len(userExt.Eids) > 0 {
 		if newUserExtBytes, err := json.Marshal(userExt); err != nil {
 			return nil, err
 		} else {
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 91ce9f0d..f2dd9815 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -104,6 +104,7 @@ const (
 	BidderBeintoo           BidderName = "beintoo"
 	BidderBetween           BidderName = "between"
 	BidderBidmachine        BidderName = "bidmachine"
+	BidderBidmyadz          BidderName = "bidmyadz"
 	BidderBidsCube          BidderName = "bidscube"
 	BidderBmtm              BidderName = "bmtm"
 	BidderBrightroll        BidderName = "brightroll"
@@ -139,6 +140,7 @@ const (
 	BidderLockerDome        BidderName = "lockerdome"
 	BidderLogicad           BidderName = "logicad"
 	BidderLunaMedia         BidderName = "lunamedia"
+	BidderSaLunaMedia       BidderName = "sa_lunamedia"
 	BidderMadvertise        BidderName = "madvertise"
 	BidderMarsmedia         BidderName = "marsmedia"
 	BidderMediafuse         BidderName = "mediafuse"
@@ -225,6 +227,7 @@ func CoreBidderNames() []BidderName {
 		BidderBeintoo,
 		BidderBetween,
 		BidderBidmachine,
+		BidderBidmyadz,
 		BidderBidsCube,
 		BidderBmtm,
 		BidderBrightroll,
@@ -260,6 +263,7 @@ func CoreBidderNames() []BidderName {
 		BidderLockerDome,
 		BidderLogicad,
 		BidderLunaMedia,
+		BidderSaLunaMedia,
 		BidderMadvertise,
 		BidderMarsmedia,
 		BidderMediafuse,
diff --git a/openrtb_ext/imp_sa_lunamedia.go b/openrtb_ext/imp_sa_lunamedia.go
new file mode 100644
index 00000000..cb99b0ac
--- /dev/null
+++ b/openrtb_ext/imp_sa_lunamedia.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ExtImpSaLunamedia struct {
+	Key  string `json:"key"`
+	Type string `json:"type,omitempty"`
+}
diff --git a/openrtb_ext/user.go b/openrtb_ext/user.go
index b83f8233..d5e6ae67 100644
--- a/openrtb_ext/user.go
+++ b/openrtb_ext/user.go
@@ -10,11 +10,6 @@ type ExtUser struct {
 
 	Prebid *ExtUserPrebid `json:"prebid,omitempty"`
 
-	// DigiTrust breaks the typical Prebid Server convention of namespacing "global" options inside "ext.prebid.*"
-	// to match the recommendation from the broader digitrust community.
-	// For more info, see: https://github.com/digi-trust/dt-cdn/wiki/OpenRTB-extension#openrtb-2x
-	DigiTrust *ExtUserDigiTrust `json:"digitrust,omitempty"`
-
 	Eids []ExtUserEid `json:"eids,omitempty"`
 }
 
@@ -23,14 +18,6 @@ type ExtUserPrebid struct {
 	BuyerUIDs map[string]string `json:"buyeruids,omitempty"`
 }
 
-// ExtUserDigiTrust defines the contract for bidrequest.user.ext.digitrust
-// More info on DigiTrust can be found here: https://github.com/digi-trust/dt-cdn/wiki/Integration-Guide
-type ExtUserDigiTrust struct {
-	ID   string `json:"id"`   // Unique device identifier
-	KeyV int    `json:"keyv"` // Key version used to encrypt ID
-	Pref int    `json:"pref"` // User optout preference
-}
-
 // ExtUserEid defines the contract for bidrequest.user.ext.eids
 // Responsible for the Universal User ID support: establishing pseudonymous IDs for users.
 // See https://github.com/prebid/Prebid.js/issues/3900 for details.
diff --git a/privacy/scrubber.go b/privacy/scrubber.go
index edaa5bb0..e07ebd05 100644
--- a/privacy/scrubber.go
+++ b/privacy/scrubber.go
@@ -225,11 +225,8 @@ func scrubUserExtIDs(userExt json.RawMessage) json.RawMessage {
 	}
 
 	_, hasEids := userExtParsed["eids"]
-	_, hasDigitrust := userExtParsed["digitrust"]
-	if hasEids || hasDigitrust {
+	if hasEids {
 		delete(userExtParsed, "eids")
-		delete(userExtParsed, "digitrust")
-
 		result, err := json.Marshal(userExtParsed)
 		if err == nil {
 			return result
diff --git a/static/bidder-info/bidmyadz.yaml b/static/bidder-info/bidmyadz.yaml
new file mode 100644
index 00000000..70a995a2
--- /dev/null
+++ b/static/bidder-info/bidmyadz.yaml
@@ -0,0 +1,13 @@
+maintainer:
+  email: "contact@bidmyadz.com"
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+      - native
+  site:
+    mediaTypes:
+      - banner
+      - video
+      - native
\ No newline at end of file
diff --git a/static/bidder-info/inmobi.yaml b/static/bidder-info/inmobi.yaml
index 9b11640f..634c0348 100644
--- a/static/bidder-info/inmobi.yaml
+++ b/static/bidder-info/inmobi.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "prebid-support@inmobi.com"
+  email: "technology-irv@inmobi.com"
 gvlVendorID: 333
 capabilities:
   app:
diff --git a/static/bidder-info/sa_lunamedia.yaml b/static/bidder-info/sa_lunamedia.yaml
new file mode 100644
index 00000000..181e1fd6
--- /dev/null
+++ b/static/bidder-info/sa_lunamedia.yaml
@@ -0,0 +1,14 @@
+maintainer:
+  email: "support@lunamedia.io"
+gvlVendorID: 998
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+      - native
+  site:
+    mediaTypes:
+      - banner
+      - video
+      - native
\ No newline at end of file
diff --git a/static/bidder-params/bidmyadz.json b/static/bidder-params/bidmyadz.json
new file mode 100644
index 00000000..4e7b1119
--- /dev/null
+++ b/static/bidder-params/bidmyadz.json
@@ -0,0 +1,12 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "BidMyAdz Adapter Params",
+    "description": "A schema which validates params accepted by the BidMyAdz adapter",
+    "type": "object",
+    "properties": {
+      "placementId": {
+        "type": "string"
+      }
+    },
+    "required": ["placementId"]
+  }
\ No newline at end of file
diff --git a/static/bidder-params/sa_lunamedia.json b/static/bidder-params/sa_lunamedia.json
new file mode 100644
index 00000000..51ca0909
--- /dev/null
+++ b/static/bidder-params/sa_lunamedia.json
@@ -0,0 +1,17 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "Sa_Lunamedia Adapter Params",
+    "description": "A schema which validates params accepted by the Sa_Lunamedia adapter",
+    "type": "object",
+    "properties": {
+      "key": {
+        "type": "string",
+        "description": "network or placement key"
+      },
+      "type": {
+        "type": "string",
+        "enum": ["network", "publisher"]
+      }
+    },
+    "required": ["key"]
+  }
\ No newline at end of file
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
index 169417e0..53472018 100644
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -28,6 +28,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/beachfront"
 	"github.com/prebid/prebid-server/adapters/beintoo"
 	"github.com/prebid/prebid-server/adapters/between"
+	"github.com/prebid/prebid-server/adapters/bidmyadz"
 	"github.com/prebid/prebid-server/adapters/bmtm"
 	"github.com/prebid/prebid-server/adapters/brightroll"
 	"github.com/prebid/prebid-server/adapters/colossus"
@@ -48,6 +49,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/grid"
 	"github.com/prebid/prebid-server/adapters/gumgum"
 	"github.com/prebid/prebid-server/adapters/improvedigital"
+	"github.com/prebid/prebid-server/adapters/inmobi"
 	"github.com/prebid/prebid-server/adapters/invibes"
 	"github.com/prebid/prebid-server/adapters/ix"
 	"github.com/prebid/prebid-server/adapters/jixie"
@@ -69,6 +71,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/rhythmone"
 	"github.com/prebid/prebid-server/adapters/rtbhouse"
 	"github.com/prebid/prebid-server/adapters/rubicon"
+	"github.com/prebid/prebid-server/adapters/sa_lunamedia"
 	"github.com/prebid/prebid-server/adapters/sharethrough"
 	"github.com/prebid/prebid-server/adapters/smartadserver"
 	"github.com/prebid/prebid-server/adapters/smartrtb"
@@ -128,6 +131,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBeintoo, beintoo.NewBeintooSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBmtm, bmtm.NewBmtmSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBrightroll, brightroll.NewBrightrollSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderBidmyadz, bidmyadz.NewBidmyadzSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderColossus, colossus.NewColossusSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderConnectAd, connectad.NewConnectAdSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderConsumable, consumable.NewConsumableSyncer)
@@ -147,6 +151,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderGrid, grid.NewGridSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderGumGum, gumgum.NewGumGumSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderImprovedigital, improvedigital.NewImprovedigitalSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderInMobi, inmobi.NewInmobiSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderInvibes, invibes.NewInvibesSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderIx, ix.NewIxSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderJixie, jixie.NewJixieSyncer)
@@ -154,6 +159,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderLockerDome, lockerdome.NewLockerDomeSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderLogicad, logicad.NewLogicadSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderLunaMedia, lunamedia.NewLunaMediaSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderSaLunaMedia, salunamedia.NewSaLunamediaSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMarsmedia, marsmedia.NewMarsmediaSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMediafuse, mediafuse.NewMediafuseSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMgid, mgid.NewMgidSyncer)


Test patch:
diff --git a/adapters/adform/adformtest/supplemental/user-nil.json b/adapters/adform/adformtest/supplemental/user-nil.json
index 5f02fe85..96ea1dbf 100644
--- a/adapters/adform/adformtest/supplemental/user-nil.json
+++ b/adapters/adform/adformtest/supplemental/user-nil.json
@@ -31,12 +31,7 @@
     },
     "user": {
       "ext": {
-        "consent": "abc2",
-        "digitrust": {
-          "ID": "digitrustId",
-          "KeyV": 1,
-          "Pref": 0
-        }
+        "consent": "abc2"
       }
     }
   },
diff --git a/adapters/bidder_test.go b/adapters/bidder_test.go
new file mode 100644
index 00000000..f0b833ce
--- /dev/null
+++ b/adapters/bidder_test.go
@@ -0,0 +1,63 @@
+package adapters
+
+import (
+	"errors"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
+)
+
+func TestExtraRequestInfoConvertCurrency(t *testing.T) {
+	var (
+		givenValue float64 = 2
+		givenFrom  string  = "AAA"
+		givenTo    string  = "BBB"
+	)
+
+	testCases := []struct {
+		description   string
+		setMock       func(m *mock.Mock)
+		expectedValue float64
+		expectedError error
+	}{
+		{
+			description:   "Success",
+			setMock:       func(m *mock.Mock) { m.On("GetRate", "AAA", "BBB").Return(2.5, nil) },
+			expectedValue: 5,
+			expectedError: nil,
+		},
+		{
+			description:   "Error",
+			setMock:       func(m *mock.Mock) { m.On("GetRate", "AAA", "BBB").Return(2.5, errors.New("some error")) },
+			expectedValue: 0,
+			expectedError: errors.New("some error"),
+		},
+	}
+
+	for _, test := range testCases {
+		mockConversions := &mockConversions{}
+		test.setMock(&mockConversions.Mock)
+
+		extraRequestInfo := NewExtraRequestInfo(mockConversions)
+		result, err := extraRequestInfo.ConvertCurrency(givenValue, givenFrom, givenTo)
+
+		mockConversions.AssertExpectations(t)
+		assert.Equal(t, test.expectedValue, result, test.description+":result")
+		assert.Equal(t, test.expectedError, err, test.description+":err")
+	}
+}
+
+type mockConversions struct {
+	mock.Mock
+}
+
+func (m mockConversions) GetRate(from string, to string) (float64, error) {
+	args := m.Called(from, to)
+	return args.Get(0).(float64), args.Error(1)
+}
+
+func (m mockConversions) GetRates() *map[string]map[string]float64 {
+	args := m.Called()
+	return args.Get(0).(*map[string]map[string]float64)
+}
diff --git a/adapters/bidmyadz/bidmyadz_test.go b/adapters/bidmyadz/bidmyadz_test.go
new file mode 100644
index 00000000..b0de6a02
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadz_test.go
@@ -0,0 +1,18 @@
+package bidmyadz
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderBidmyadz, config.Adapter{
+		Endpoint: "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc"})
+
+	assert.NoError(t, buildErr)
+	adapterstest.RunJSONBidderTest(t, "bidmyadztest", bidder)
+}
diff --git a/adapters/bidmyadz/bidmyadztest/exemplary/banner.json b/adapters/bidmyadz/bidmyadztest/exemplary/banner.json
new file mode 100644
index 00000000..460291bc
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/exemplary/banner.json
@@ -0,0 +1,146 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "1"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "1"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "d910ceef496ff2d746176506e296f4b3_z53356_a126365",
+          "bidid": "880184da7ec02b1f42802acb46b63b3c",
+          "seatbid": [{
+            "bid": [{
+              "id": "6ca51ef38eb42820d27503ee96b634b5",
+              "impid": "126365",
+              "price": 0.1,
+              "nurl": "http://test.com/nurl",
+              "burl": "http://test.com/burl",
+              "adm": "<ADM>",
+              "adomain": ["test.com"],
+              "cat": ["IAB1"],
+              "cid": "1",
+              "crid": "1",
+              "w": 300,
+              "h": 250,
+              "ext": {
+                "mediaType": "banner"
+              }
+            }],
+            "seat": "1"
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "6ca51ef38eb42820d27503ee96b634b5",
+            "impid": "126365",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "<ADM>",
+            "adomain": ["test.com"],
+            "cat": ["IAB1"],
+            "cid": "1",
+            "crid": "1",
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "mediaType": "banner"
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/exemplary/native.json b/adapters/bidmyadz/bidmyadztest/exemplary/native.json
new file mode 100644
index 00000000..98480260
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/exemplary/native.json
@@ -0,0 +1,141 @@
+{
+  "mockBidRequest": {
+    "id": "111",
+    "tmax": 150,
+    "at": 1,
+    "device": {
+      "dnt": 0,
+      "devicetype": 2,
+      "ip": "71.106.52.124",
+      "ua": "Mozilla/5.0 (X11; Linux x86_64; Ubuntu 14.04.2 LTS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.0 Maxthon/1.0.5.3 Safari/537.36"
+    },
+    "user": {
+      "id": "user-id"
+    },
+    "site": {
+      "id": "native",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "1"
+      }
+    },
+    "cur": [
+      "USD"
+    ],
+    "imp": [{
+      "id": "1",
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "instl": 0,
+      "secure": 1,
+      "native": {
+        "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":15}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":300,\"hmin\":300,\"type\":3}}, {\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+        "ver": "1.1"
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tnative"
+        }
+      }
+    }]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+      "body": {
+        "id": "111",
+        "tmax": 150,
+        "at": 1,
+        "device": {
+          "dnt": 0,
+          "devicetype": 2,
+          "ip": "71.106.52.124",
+          "ua": "Mozilla/5.0 (X11; Linux x86_64; Ubuntu 14.04.2 LTS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.0 Maxthon/1.0.5.3 Safari/537.36"
+        },
+        "user": {
+          "id": "user-id"
+        },
+        "site": {
+          "id": "native",
+          "domain": "test.com",
+          "cat": ["IAB1"],
+          "page": "https://test.com",
+          "publisher": {
+            "id": "1"
+          }
+        },
+        "cur": [
+          "USD"
+        ],
+        "imp": [{
+          "id": "1",
+          "bidfloor": 0.01,
+          "bidfloorcur": "USD",
+          "secure": 1,
+          "native": {
+            "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":15}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":300,\"hmin\":300,\"type\":3}}, {\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+            "ver": "1.1"
+          },
+          "ext": {
+            "bidder": {
+              "placementId": "tnative"
+            }
+          }
+        }]
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "a1580f2f-be6d-11eb-a150-d094662c1c35",
+        "bidid": "359da97d0384d8a14767029c18fd840d",
+        "seatbid": [{
+          "bid": [{
+            "id": "1",
+            "impid": "1",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "{native-ads}",
+            "adomain": ["test.com"],
+            "cat": ["IAB1"],
+            "cid": "1",
+            "crid": "2",
+            "w": 0,
+            "h": 0,
+            "ext": {
+              "mediaType": "native"
+            }
+          }],
+          "seat": "1"
+        }],
+        "cur": "USD"
+      }
+    }
+  }],
+
+  "expectedBidResponses": [{
+    "currency": "USD",
+    "bids": [{
+      "bid": {
+        "id": "1",
+        "impid": "1",
+        "price": 0.1,
+        "nurl": "http://test.com/nurl",
+        "burl": "http://test.com/burl",
+        "adm": "{native-ads}",
+        "adomain": ["test.com"],
+        "cat": ["IAB1"],
+        "cid": "1",
+        "crid": "2",
+        "ext": {
+          "mediaType": "native"
+        }
+      },
+      "type": "native"
+    }]
+  }]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/exemplary/video.json b/adapters/bidmyadz/bidmyadztest/exemplary/video.json
new file mode 100644
index 00000000..92c42f83
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/exemplary/video.json
@@ -0,0 +1,160 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "video": {
+        "mimes": ["video/mp4", "video/ogg", "video/webm"],
+        "minduration": 5,
+        "maxduration": 60,
+        "protocols": [2, 3, 5, 6, 7, 8],
+        "w": 300,
+        "h": 250,
+        "linearity": 1,
+        "playbackmethod": [2]
+      },
+      "bidfloor": 0.001,
+      "bidfloorcur": "USD",
+      "secure": 1,
+      "exp": 3600,
+      "ext": {
+        "bidder": {
+          "placementId": "tvideo"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "1"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "video": {
+              "mimes": ["video/mp4", "video/ogg", "video/webm"],
+              "minduration": 5,
+              "maxduration": 60,
+              "protocols": [2, 3, 5, 6, 7, 8],
+              "w": 300,
+              "h": 250,
+              "linearity": 1,
+              "playbackmethod": [2]
+            },
+            "bidfloor": 0.001,
+            "bidfloorcur": "USD",
+            "secure": 1,
+            "exp": 3600,
+            "ext": {
+              "bidder": {
+                "placementId": "tvideo"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "1"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "d910ceef496ff2d746176506e296f4b3_z53356_a126365",
+          "bidid": "880184da7ec02b1f42802acb46b63b3c",
+          "seatbid": [{
+            "bid": [{
+              "id": "6ca51ef38eb42820d27503ee96b634b5",
+              "impid": "126365",
+              "price": 0.1,
+              "nurl": "http://test.com/nurl",
+              "burl": "http://test.com/burl",
+              "adm": "<VAST>",
+              "adomain": ["test.com"],
+              "cat": ["IAB1"],
+              "cid": "1",
+              "crid": "1",
+              "w": 300,
+              "h": 250,
+              "ext": {
+                "mediaType": "video"
+              }
+            }],
+            "seat": "1"
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "6ca51ef38eb42820d27503ee96b634b5",
+            "impid": "126365",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "<VAST>",
+            "adomain": ["test.com"],
+            "cat": ["IAB1"],
+            "cid": "1",
+            "crid": "1",
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "mediaType": "video"
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/params/race/banner.json b/adapters/bidmyadz/bidmyadztest/params/race/banner.json
new file mode 100644
index 00000000..18dce42f
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/params/race/banner.json
@@ -0,0 +1,3 @@
+{
+  "placementId": "tbanner"
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/params/race/native.json b/adapters/bidmyadz/bidmyadztest/params/race/native.json
new file mode 100644
index 00000000..0600af3a
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/params/race/native.json
@@ -0,0 +1,3 @@
+{
+  "placementId": "tnative"
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/params/race/video.json b/adapters/bidmyadz/bidmyadztest/params/race/video.json
new file mode 100644
index 00000000..85478bf2
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/params/race/video.json
@@ -0,0 +1,3 @@
+{
+  "placementId": "tvideo"
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/invalid-device-fields.json b/adapters/bidmyadz/bidmyadztest/supplemental/invalid-device-fields.json
new file mode 100644
index 00000000..d620a050
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/invalid-device-fields.json
@@ -0,0 +1,48 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "devicetype": 2
+    },
+    "user": {
+      "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "test"
+      }
+    }
+  },
+
+  "expectedMakeRequestsErrors": [{
+    "value": "IP/IPv6 is a required field",
+    "comparison": "literal"
+  }, {
+    "value": "User-Agent is a required field",
+    "comparison": "literal"
+  }]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/invalid-multi-imps.json b/adapters/bidmyadz/bidmyadztest/supplemental/invalid-multi-imps.json
new file mode 100644
index 00000000..09020fc8
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/invalid-multi-imps.json
@@ -0,0 +1,61 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }, {
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.11,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 320,
+        "h": 50
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "3234"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "test"
+      }
+    }
+  },
+
+  "expectedMakeRequestsErrors": [{
+    "value": "Bidder does not support multi impression",
+    "comparison": "literal"
+  }]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/missing-mediatype.json b/adapters/bidmyadz/bidmyadztest/supplemental/missing-mediatype.json
new file mode 100644
index 00000000..486d7324
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/missing-mediatype.json
@@ -0,0 +1,122 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "1"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "1"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "d910ceef496ff2d746176506e296f4b3_z53356_a126365",
+          "bidid": "880184da7ec02b1f42802acb46b63b3c",
+          "seatbid": [{
+            "bid": [{
+              "id": "6ca51ef38eb42820d27503ee96b634b5",
+              "impid": "126365",
+              "price": 0.1,
+              "nurl": "http://test.com/nurl",
+              "burl": "http://test.com/burl",
+              "adm": "<ADM>",
+              "adomain": ["test.com"],
+              "cat": ["IAB1"],
+              "cid": "1",
+              "crid": "1",
+              "w": 300,
+              "h": 250
+            }],
+            "seat": "1"
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "BidExt parsing error. unexpected end of JSON input",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/response-without-bids.json b/adapters/bidmyadz/bidmyadztest/supplemental/response-without-bids.json
new file mode 100644
index 00000000..fe3361f6
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/response-without-bids.json
@@ -0,0 +1,109 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "1"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "1"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "d910ceef496ff2d746176506e296f4b3_z53356_a126365",
+          "bidid": "880184da7ec02b1f42802acb46b63b3c",
+          "seatbid": [{
+            "bid": [],
+            "seat": "1"
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Empty SeatBid.Bids",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/response-without-seatbid.json b/adapters/bidmyadz/bidmyadztest/supplemental/response-without-seatbid.json
new file mode 100644
index 00000000..727e745e
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/response-without-seatbid.json
@@ -0,0 +1,106 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "1"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "a66e61ff8c2ab5460ecf156c4b892fd84d41fad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "1"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "d910ceef496ff2d746176506e296f4b3_z53356_a126365",
+          "bidid": "880184da7ec02b1f42802acb46b63b3c",
+          "seatbid": [],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Empty SeatBid",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/status-204.json b/adapters/bidmyadz/bidmyadztest/supplemental/status-204.json
new file mode 100644
index 00000000..05efda0e
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/status-204.json
@@ -0,0 +1,94 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "test"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "test"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": {}
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/status-400.json b/adapters/bidmyadz/bidmyadztest/supplemental/status-400.json
new file mode 100644
index 00000000..e24acdc6
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/status-400.json
@@ -0,0 +1,101 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "test"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "test"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 400,
+        "body": "Source blocked"
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad Request. \"Source blocked\"",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/status-service-unavailable.json b/adapters/bidmyadz/bidmyadztest/supplemental/status-service-unavailable.json
new file mode 100644
index 00000000..13e22f55
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/status-service-unavailable.json
@@ -0,0 +1,100 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "test"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "test"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 503
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bidder is unavailable. Please contact your account manager.",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/bidmyadztest/supplemental/status-unknown.json b/adapters/bidmyadz/bidmyadztest/supplemental/status-unknown.json
new file mode 100644
index 00000000..69b649e1
--- /dev/null
+++ b/adapters/bidmyadz/bidmyadztest/supplemental/status-unknown.json
@@ -0,0 +1,101 @@
+{
+  "mockBidRequest": {
+    "id": "12345",
+    "imp": [{
+      "id": "1",
+      "secure": 1,
+      "bidfloor": 0.31,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "placementId": "tbanner"
+        }
+      }
+    }],
+    "device": {
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "ip": "18.146.18.241",
+      "devicetype": 2
+    },
+    "user": {
+      "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+    },
+    "site": {
+      "id": "banner",
+      "domain": "test.com",
+      "cat": ["IAB1"],
+      "page": "https://test.com",
+      "publisher": {
+        "id": "test"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://endpoint.bidmyadz.com/c0f68227d14ed938c6c49f3967cbe9bc",
+        "body": {
+          "id": "12345",
+          "imp": [{
+            "id": "1",
+            "secure": 1,
+            "bidfloor": 0.31,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "placementId": "tbanner"
+              }
+            }
+          }],
+          "device": {
+            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
+            "geo": {
+              "country": "USA",
+              "lat": 47.627500,
+              "lon": -122.346200
+            },
+            "ip": "18.146.18.241",
+            "devicetype": 2
+          },
+          "user": {
+            "id": "460ecf1d41fa6656c4b892fd84e61ff8c2ab5ad5"
+          },
+          "site": {
+            "id": "banner",
+            "domain": "test.com",
+            "cat": ["IAB1"],
+            "page": "https://test.com",
+            "publisher": {
+              "id": "test"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 403,
+        "body": "Forbidden"
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Something went wrong. Status Code: [ 403 ] \"Forbidden\"",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/bidmyadz/params_test.go b/adapters/bidmyadz/params_test.go
new file mode 100644
index 00000000..857cde86
--- /dev/null
+++ b/adapters/bidmyadz/params_test.go
@@ -0,0 +1,49 @@
+package bidmyadz
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+var validParams = []string{
+	`{ "placementId": "1234" }`,
+}
+
+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.BidderBidmyadz, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected bidmyadz params: %s", validParam)
+		}
+	}
+}
+
+var invalidParams = []string{
+	`1234`,
+	``,
+	`true`,
+	`null`,
+	`[]`,
+	`{}`,
+	`{ "anyparam": "anyvalue" }`,
+	`{ "placementId": null }`,
+}
+
+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.BidderBidmyadz, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
diff --git a/adapters/bidmyadz/usersync_test.go b/adapters/bidmyadz/usersync_test.go
new file mode 100644
index 00000000..11b5fedd
--- /dev/null
+++ b/adapters/bidmyadz/usersync_test.go
@@ -0,0 +1,33 @@
+package bidmyadz
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/ccpa"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewBidmyadzSyncer(t *testing.T) {
+	syncURL := "https://test.com/c0f68227d14ed938c6c49f3967cbe9bc?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ccpa={{.USPrivacy}}"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+	syncer := NewBidmyadzSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "0",
+			Consent: "allGdpr",
+		},
+		CCPA: ccpa.Policy{
+			Consent: "1---",
+		},
+	})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "https://test.com/c0f68227d14ed938c6c49f3967cbe9bc?gdpr=0&gdpr_consent=allGdpr&ccpa=1---", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/adapters/dmx/dmx_test.go b/adapters/dmx/dmx_test.go
index a9f1e8bb..409290c1 100644
--- a/adapters/dmx/dmx_test.go
+++ b/adapters/dmx/dmx_test.go
@@ -643,50 +643,6 @@ func TestUserEidsOnly(t *testing.T) {
 	}
 }
 
-func TestUserDigitrustOnly(t *testing.T) {
-	var w, h int = 300, 250
-
-	var width, height int64 = int64(w), int64(h)
-
-	bidder, buildErr := Builder(openrtb_ext.BidderDmx, config.Adapter{
-		Endpoint: "https://dmx.districtm.io/b/v2"})
-
-	if buildErr != nil {
-		t.Fatalf("Builder returned unexpected error %v", buildErr)
-	}
-
-	imp1 := openrtb2.Imp{
-		ID:  "imp1",
-		Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
-		Banner: &openrtb2.Banner{
-			W: &width,
-			H: &height,
-			Format: []openrtb2.Format{
-				{W: 300, H: 250},
-			},
-		}}
-
-	inputRequest := openrtb2.BidRequest{
-		Imp: []openrtb2.Imp{imp1, imp1, imp1},
-		Site: &openrtb2.Site{
-			Publisher: &openrtb2.Publisher{
-				ID: "10007",
-			},
-		},
-		User: &openrtb2.User{Ext: json.RawMessage(`{
-            "digitrust": {
-                "id": "11111111111",
-                "keyv": 4
-            }}`)},
-		ID: "1234",
-	}
-
-	actualAdapterRequests, _ := bidder.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
-	if len(actualAdapterRequests) != 1 {
-		t.Errorf("should have 1 request")
-	}
-}
-
 func TestUsersEids(t *testing.T) {
 	var w, h int = 300, 250
 
@@ -725,53 +681,56 @@ func TestUsersEids(t *testing.T) {
                         "rtiPartner": "TDID"
                     }
                 }]
-            },{
+            },
+			{
                 "source": "pubcid.org",
                 "uids": [{
-                    "id":"11111111"
+                    "id": "11111111"
                 }]
             },
-            {
+			{
                 "source": "id5-sync.com",
                 "uids": [{
                     "id": "ID5-12345"
                 }]
-            },
-            {
+            },            
+			{
                 "source": "parrable.com",
                 "uids": [{
                     "id": "01.1563917337.test-eid"
                 }]
-            },{
+            },
+			{
                 "source": "identityLink",
                 "uids": [{
                     "id": "11111111"
                 }]
-            },{
+            },
+			{
                 "source": "criteo",
                 "uids": [{
                     "id": "11111111"
                 }]
-            },{
+            },
+			{
                 "source": "britepool.com",
                 "uids": [{
                     "id": "11111111"
                 }]
-            },{
+            },
+			{
                 "source": "liveintent.com",
                 "uids": [{
                     "id": "11111111"
                 }]
-            },{
+            },
+			{
                 "source": "netid.de",
                 "uids": [{
                     "id": "11111111"
                 }]
-            }],
-            "digitrust": {
-                "id": "11111111111",
-                "keyv": 4
-            }}`)},
+            }]
+            }`)},
 		ID: "1234",
 	}
 
diff --git a/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json b/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json
new file mode 100644
index 00000000..36a23998
--- /dev/null
+++ b/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json
@@ -0,0 +1,104 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "native": {
+                    "request": "{}",
+                    "ver": "1.1"
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ]
+    },
+    "httpcalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "native": {
+                                "request": "{}",
+                                "ver": "1.1"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"eventtrackers\":[{\"url\":\"https://example.com/imp-2.gif\",\"event\":1,\"method\":1},{\"url\":\"https://example.com/imp-3.gif\",\"event\":1,\"method\":1}],\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"]}",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "cat": [
+                                        "IAB3-1"
+                                    ],
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adid": "29681110",
+                        "adm": "{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\",\"https://example.com/imp-3.gif\"],\"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"https://example.com/imp-2.gif\"},{\"event\":1,\"method\":1,\"url\":\"https://example.com/imp-3.gif\"}]}",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "cat": [
+                            "IAB3-1"
+                        ],
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/ix/ixtest/supplemental/bad-imp-id.json b/adapters/ix/ixtest/supplemental/bad-imp-id.json
index 0b852c85..1ca053b6 100644
--- a/adapters/ix/ixtest/supplemental/bad-imp-id.json
+++ b/adapters/ix/ixtest/supplemental/bad-imp-id.json
@@ -111,7 +111,7 @@
     ],
     "expectedMakeBidsErrors": [
         {
-            "value": "Unmatched impression id: bad-imp-id.",
+            "value": "unmatched impression id: bad-imp-id",
             "comparison": "literal"
         }
     ]
diff --git a/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json b/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json
new file mode 100644
index 00000000..4cf314e7
--- /dev/null
+++ b/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json
@@ -0,0 +1,104 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "native": {
+                    "request": "{}",
+                    "ver": "1.1"
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ]
+    },
+    "httpcalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "native": {
+                                "request": "{}",
+                                "ver": "1.1"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"],\"eventtrackers\":[]}}",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "cat": [
+                                        "IAB3-1"
+                                    ],
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adid": "29681110",
+                        "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"],\"eventtrackers\":[]}}",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "cat": [
+                            "IAB3-1"
+                        ],
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json b/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json
new file mode 100644
index 00000000..d8c78a5c
--- /dev/null
+++ b/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json
@@ -0,0 +1,104 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "native": {
+                    "request": "{}",
+                    "ver": "1.1"
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ]
+    },
+    "httpcalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "native": {
+                                "request": "{}",
+                                "ver": "1.1"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"]}}",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "cat": [
+                                        "IAB3-1"
+                                    ],
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adid": "29681110",
+                        "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"]}}",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "cat": [
+                            "IAB3-1"
+                        ],
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/ix/ixtest/supplemental/native-missing.json b/adapters/ix/ixtest/supplemental/native-missing.json
new file mode 100644
index 00000000..ec2108ce
--- /dev/null
+++ b/adapters/ix/ixtest/supplemental/native-missing.json
@@ -0,0 +1,104 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "native": {
+                    "request": "{}",
+                    "ver": "1.1"
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ]
+    },
+    "httpcalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "native": {
+                                "request": "{}",
+                                "ver": "1.1"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "{\"native\":{}}",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "cat": [
+                                        "IAB3-1"
+                                    ],
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adid": "29681110",
+                        "adm": "{\"native\":{}}",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "cat": [
+                            "IAB3-1"
+                        ],
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/rubicon/rubicon_test.go b/adapters/rubicon/rubicon_test.go
index 8f8d3fb1..76904a42 100644
--- a/adapters/rubicon/rubicon_test.go
+++ b/adapters/rubicon/rubicon_test.go
@@ -1035,15 +1035,15 @@ func TestOpenRTBRequest(t *testing.T) {
 				}
 			}}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 		Device: &openrtb2.Device{
 			PxRatio: rubidata.devicePxRatio,
 		},
 		User: &openrtb2.User{
-			Ext: json.RawMessage(`{"digitrust": {
-                    "id": "some-digitrust-id",
-                    "keyv": 1,
-                    "pref": 0
-                },
+			Ext: json.RawMessage(`{
 				"eids": [{
                     "source": "pubcid",
                     "id": "2402fc76-7b39-4f0e-bfc2-060ef7693648"
@@ -1117,10 +1117,6 @@ func TestOpenRTBRequest(t *testing.T) {
 			t.Fatal("Error unmarshalling request.user.ext object.")
 		}
 
-		assert.Equal(t, "some-digitrust-id", userExt.DigiTrust.ID, "DigiTrust ID id not as expected!")
-		assert.Equal(t, 1, userExt.DigiTrust.KeyV, "DigiTrust KeyV id not as expected!")
-		assert.Equal(t, 0, userExt.DigiTrust.Pref, "DigiTrust Pref id not as expected!")
-
 		assert.NotNil(t, userExt.Eids)
 		assert.Equal(t, 1, len(userExt.Eids), "Eids values are not as expected!")
 		assert.Contains(t, userExt.Eids, openrtb_ext.ExtUserEid{Source: "pubcid", ID: "2402fc76-7b39-4f0e-bfc2-060ef7693648"})
@@ -1154,6 +1150,10 @@ func TestOpenRTBRequestWithBannerImpEvenIfImpHasVideo(t *testing.T) {
 				"visitor": {"key2" : "val2"}
 			}}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 	}
 
 	reqs, errs := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{})
@@ -1203,6 +1203,10 @@ func TestOpenRTBRequestWithImpAndAdSlotIncluded(t *testing.T) {
 				}
 			}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 	}
 
 	reqs, _ := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{})
@@ -1258,6 +1262,10 @@ func TestOpenRTBRequestWithBadvOverflowed(t *testing.T) {
 				}
 			}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 	}
 
 	reqs, _ := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{})
@@ -1291,6 +1299,10 @@ func TestOpenRTBRequestWithSpecificExtUserEids(t *testing.T) {
 				"accountId": 7891
 			}}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 		User: &openrtb2.User{
 			Ext: json.RawMessage(`{"eids": [
 			{
@@ -1399,6 +1411,10 @@ func TestOpenRTBRequestWithVideoImpEvenIfImpHasBannerButAllRequiredVideoFields(t
 				"video": {"size_id": 1}
 			}}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 	}
 
 	reqs, errs := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{})
@@ -1444,6 +1460,10 @@ func TestOpenRTBRequestWithVideoImpAndEnabledRewardedInventoryFlag(t *testing.T)
 				"video": {"size_id": 1}
 			}}`),
 		}},
+		App: &openrtb2.App{
+			ID:   "com.test",
+			Name: "testApp",
+		},
 	}
 
 	reqs, _ := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{})
diff --git a/adapters/rubicon/rubicontest/exemplary/simple-video.json b/adapters/rubicon/rubicontest/exemplary/simple-video.json
index a90670e5..11afdd50 100644
--- a/adapters/rubicon/rubicontest/exemplary/simple-video.json
+++ b/adapters/rubicon/rubicontest/exemplary/simple-video.json
@@ -9,11 +9,50 @@
       "id": "1",
       "bundle": "com.wls.testwlsapplication"
     },
+    "site": {
+      "content": {
+        "data": [
+          {
+            "ext": {
+              "segtax": 1
+            },
+            "segment": [
+              {
+                "id": "segmentId1"
+              },
+              {
+                "id": "segmentId2"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": "1"
+            },
+            "segment": [
+              {
+                "id": "shouldNotBeCopied"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": 2
+            },
+            "segment": [
+              {
+                "id": "segmentId3"
+              }
+            ]
+          }
+        ]
+      }
+    },
     "user": {
       "data": [
         {
           "ext": {
-            "taxonomyname": "iab"
+            "segtax": 4
           },
           "segment": [
             {
@@ -23,7 +62,7 @@
         },
         {
           "ext": {
-            "taxonomyname": "someValue"
+            "segtax": "someValue"
           },
           "segment": [
             {
@@ -33,7 +72,17 @@
         },
         {
           "ext": {
-            "taxonomyname": "IaB"
+            "segtax": "4"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": 4
           },
           "segment": [
             {
@@ -43,13 +92,13 @@
         },
         {
           "ext": {
-            "taxonomyname": [
-              "wrong iab type"
+            "segtax": [
+              4
             ]
           },
           "segment": [
             {
-              "id": "shouldNotBeCopied2"
+              "id": "shouldNotBeCopied3"
             }
           ]
         }
@@ -100,11 +149,69 @@
             "ip": "123.123.123.123",
             "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
           },
+          "site": {
+            "content": {
+              "data": [
+                {
+                  "ext": {
+                    "segtax": 1
+                  },
+                  "segment": [
+                    {
+                      "id": "segmentId1"
+                    },
+                    {
+                      "id": "segmentId2"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": "1"
+                  },
+                  "segment": [
+                    {
+                      "id": "shouldNotBeCopied"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": 2
+                  },
+                  "segment": [
+                    {
+                      "id": "segmentId3"
+                    }
+                  ]
+                }
+              ]
+            },
+            "ext": {
+              "rp": {
+                "site_id": 113932,
+                "target": {
+                  "iab": [
+                    "segmentId1",
+                    "segmentId2",
+                    "segmentId3"
+                  ]
+                }
+              }
+            },
+            "publisher": {
+              "ext": {
+                "rp": {
+                  "account_id": 1001
+                }
+              }
+            }
+          },
           "user": {
             "data": [
               {
                 "ext": {
-                  "taxonomyname": "iab"
+                  "segtax": 4
                 },
                 "segment": [
                   {
@@ -114,7 +221,7 @@
               },
               {
                 "ext": {
-                  "taxonomyname": "someValue"
+                  "segtax": "someValue"
                 },
                 "segment": [
                   {
@@ -124,7 +231,17 @@
               },
               {
                 "ext": {
-                  "taxonomyname": "IaB"
+                  "segtax": "4"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": 4
                 },
                 "segment": [
                   {
@@ -134,19 +251,18 @@
               },
               {
                 "ext": {
-                  "taxonomyname": [
-                    "wrong iab type"
+                  "segtax": [
+                    4
                   ]
                 },
                 "segment": [
                   {
-                    "id": "shouldNotBeCopied2"
+                    "id": "shouldNotBeCopied3"
                   }
                 ]
               }
             ],
             "ext": {
-              "digitrust": null,
               "rp": {
                 "target": {
                   "iab": [
@@ -159,18 +275,6 @@
           },
           "app": {
             "id": "1",
-            "ext": {
-              "rp": {
-                "site_id": 113932
-              }
-            },
-            "publisher": {
-              "ext": {
-                "rp": {
-                  "account_id": 1001
-                }
-              }
-            },
             "bundle": "com.wls.testwlsapplication"
           },
           "imp": [
diff --git a/adapters/sa_lunamedia/params_test.go b/adapters/sa_lunamedia/params_test.go
new file mode 100644
index 00000000..bf7a1f49
--- /dev/null
+++ b/adapters/sa_lunamedia/params_test.go
@@ -0,0 +1,52 @@
+package salunamedia
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+var validParams = []string{
+	`{ "key": "2", "type": "network"}`,
+	`{ "key": "1"}`,
+	`{ "key": "33232", "type": "publisher"}`,
+}
+
+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.BidderSaLunaMedia, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected sa_lunamedia params: %s", validParam)
+		}
+	}
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`[]`,
+	`{}`,
+	`{ "anyparam": "anyvalue" }`,
+	`{ "type": "network" }`,
+	`{ "key": "asddsfd", "type": "any"}`,
+}
+
+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.BidderSaLunaMedia, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
diff --git a/adapters/sa_lunamedia/salunamedia_test.go b/adapters/sa_lunamedia/salunamedia_test.go
new file mode 100644
index 00000000..f5d20582
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamedia_test.go
@@ -0,0 +1,18 @@
+package salunamedia
+
+import (
+	"testing"
+
+	"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"
+)
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderSaLunaMedia, config.Adapter{
+		Endpoint: "http://test.com/pserver"})
+
+	assert.NoError(t, buildErr)
+	adapterstest.RunJSONBidderTest(t, "salunamediatest", bidder)
+}
diff --git a/adapters/sa_lunamedia/salunamediatest/exemplary/banner.json b/adapters/sa_lunamedia/salunamediatest/exemplary/banner.json
new file mode 100644
index 00000000..2ce4ad81
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/exemplary/banner.json
@@ -0,0 +1,142 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [{
+            "id": "id",
+            "secure": 1,
+            "bidfloor": 0.01,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "key": "test"
+              }
+            }
+          }],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": ["IAB12"],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "seatbid": [{
+            "bid": [{
+              "id": "id",
+              "impid": "id",
+              "price": 0.1,
+              "nurl": "http://test.com/nurl",
+              "burl": "http://test.com/burl",
+              "adm": "<span>Test</span>",
+              "adomain": ["test.com"],
+              "cat": ["IAB1"],
+              "cid": "cid",
+              "crid": "crid",
+              "w": 300,
+              "h": 250,
+              "ext": {
+                "mediaType": "banner"
+              }
+            }],
+            "seat": "seat"
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "id",
+            "impid": "id",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "<span>Test</span>",
+            "adomain": ["test.com"],
+            "cat": ["IAB1"],
+            "cid": "cid",
+            "crid": "crid",
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "mediaType": "banner"
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/exemplary/native.json b/adapters/sa_lunamedia/salunamediatest/exemplary/native.json
new file mode 100644
index 00000000..74d8940f
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/exemplary/native.json
@@ -0,0 +1,132 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "native": {
+        "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+        "ver": "1.1"
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://test.com/pserver",
+      "body": {
+        "id": "id",
+        "imp": [{
+          "id": "id",
+          "secure": 1,
+          "bidfloor": 0.01,
+          "bidfloorcur": "USD",
+          "native": {
+            "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+            "ver": "1.1"
+          },
+          "ext": {
+            "bidder": {
+              "key": "test"
+            }
+          }
+        }],
+        "device": {
+          "ua": "UA",
+          "ip": "123.3.4.123"
+        },
+        "regs": {
+          "ext": {
+            "gdpr": 0
+          }
+        },
+        "user": {
+          "id": "userid"
+        },
+        "site": {
+          "id": "id",
+          "domain": "test,com",
+          "cat": ["IAB12"],
+          "publisher": {
+            "id": "pubid"
+          }
+        }
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "id",
+        "bidid": "id",
+        "seatbid": [{
+          "bid": [{
+            "id": "id",
+            "impid": "id",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "{}",
+            "adomain": ["test.com"],
+            "cat": ["IAB1"],
+            "cid": "cid",
+            "crid": "crid",
+            "ext": {
+              "mediaType": "native"
+            }
+          }],
+          "seat": "seat"
+        }],
+        "cur": "USD"
+      }
+    }
+  }],
+
+  "expectedBidResponses": [{
+    "currency": "USD",
+    "bids": [{
+      "bid": {
+        "id": "id",
+        "impid": "id",
+        "price": 0.1,
+        "nurl": "http://test.com/nurl",
+        "burl": "http://test.com/burl",
+        "adm": "{}",
+        "adomain": ["test.com"],
+        "cat": ["IAB1"],
+        "cid": "cid",
+        "crid": "crid",
+        "ext": {
+          "mediaType": "native"
+        }
+      },
+      "type": "native"
+    }]
+  }]
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/exemplary/video.json b/adapters/sa_lunamedia/salunamediatest/exemplary/video.json
new file mode 100644
index 00000000..9a042d72
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/exemplary/video.json
@@ -0,0 +1,169 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "video": {
+        "mimes": ["video/mp4", "video/ogg", "video/webm"],
+        "minduration": 3,
+        "maxduration": 3000,
+        "protocols": [2, 3, 5, 6, 7, 8],
+        "w": 480,
+        "h": 320,
+        "linearity": 1,
+        "playbackmethod": [2],
+        "pos": 0
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [
+            {
+              "id": "id",
+              "secure": 1,
+              "bidfloor": 0.01,
+              "bidfloorcur": "USD",
+              "video": {
+                "mimes": [
+                  "video/mp4",
+                  "video/ogg",
+                  "video/webm"
+                ],
+                "minduration": 3,
+                "maxduration": 3000,
+                "protocols": [
+                  2,
+                  3,
+                  5,
+                  6,
+                  7,
+                  8
+                ],
+                "w": 480,
+                "h": 320,
+                "linearity": 1,
+                "playbackmethod": [
+                  2
+                ],
+                "pos": 0
+              },
+              "ext": {
+                "bidder": {
+                  "key": "test"
+                }
+              }
+            }
+          ],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": [
+              "IAB12"
+            ],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "id",
+          "bidid": "id",
+          "seatbid": [{
+            "bid": [{
+              "id": "id",
+              "impid": "id",
+              "price": 0.1,
+              "nurl": "http://test.com/nurl",
+              "burl": "http://test.com/burl",
+              "adm": "<VAST>",
+              "adomain": ["test.com"],
+              "cat": ["IAB1"],
+              "cid": "cid",
+              "crid": "crid",
+              "ext": {
+                "mediaType": "video"
+              }
+            }],
+            "seat": "seat"
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "id",
+            "impid": "id",
+            "price": 0.1,
+            "nurl": "http://test.com/nurl",
+            "burl": "http://test.com/burl",
+            "adm": "<VAST>",
+            "adomain": ["test.com"],
+            "cat": ["IAB1"],
+            "cid": "cid",
+            "crid": "crid",
+            "ext": {
+              "mediaType": "video"
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/params/race/banner.json b/adapters/sa_lunamedia/salunamediatest/params/race/banner.json
new file mode 100644
index 00000000..c02a5de9
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/params/race/banner.json
@@ -0,0 +1,3 @@
+{
+  "key": "test"
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/params/race/native.json b/adapters/sa_lunamedia/salunamediatest/params/race/native.json
new file mode 100644
index 00000000..c02a5de9
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/params/race/native.json
@@ -0,0 +1,3 @@
+{
+  "key": "test"
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/params/race/video.json b/adapters/sa_lunamedia/salunamediatest/params/race/video.json
new file mode 100644
index 00000000..c02a5de9
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/params/race/video.json
@@ -0,0 +1,3 @@
+{
+  "key": "test"
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/supplemental/bad-response.json b/adapters/sa_lunamedia/salunamediatest/supplemental/bad-response.json
new file mode 100644
index 00000000..6373207d
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/supplemental/bad-response.json
@@ -0,0 +1,98 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [{
+            "id": "id",
+            "secure": 1,
+            "bidfloor": 0.01,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "key": "test"
+              }
+            }
+          }],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": ["IAB12"],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": ""
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+      "comparison": "literal"
+    }
+  ],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/supplemental/empty-seatbid.json b/adapters/sa_lunamedia/salunamediatest/supplemental/empty-seatbid.json
new file mode 100644
index 00000000..8942b3be
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/supplemental/empty-seatbid.json
@@ -0,0 +1,102 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://test.com/pserver",
+      "body": {
+        "id": "id",
+        "imp": [{
+          "id": "id",
+          "secure": 1,
+          "bidfloor": 0.01,
+          "bidfloorcur": "USD",
+          "banner": {
+            "w": 300,
+            "h": 250
+          },
+          "ext": {
+            "bidder": {
+              "key": "test"
+            }
+          }
+        }],
+        "device": {
+          "ua": "UA",
+          "ip": "123.3.4.123"
+        },
+        "regs": {
+          "ext": {
+            "gdpr": 0
+          }
+        },
+        "user": {
+          "id": "userid"
+        },
+        "site": {
+          "id": "id",
+          "domain": "test,com",
+          "cat": ["IAB12"],
+          "publisher": {
+            "id": "pubid"
+          }
+        }
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "a1580f2f-be6d-11eb-a150-d094662c1c35",
+        "bidid": "359da97d0384d8a14767029c18fd840d",
+        "seatbid": [],
+        "cur": "USD"
+      }
+    }
+  }],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Empty SeatBid",
+      "comparison": "literal"
+    }
+  ],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/supplemental/status-204.json b/adapters/sa_lunamedia/salunamediatest/supplemental/status-204.json
new file mode 100644
index 00000000..042b96bd
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/supplemental/status-204.json
@@ -0,0 +1,92 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [{
+            "id": "id",
+            "secure": 1,
+            "bidfloor": 0.01,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "key": "test"
+              }
+            }
+          }],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": ["IAB12"],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/supplemental/status-400.json b/adapters/sa_lunamedia/salunamediatest/supplemental/status-400.json
new file mode 100644
index 00000000..1ecdc46e
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/supplemental/status-400.json
@@ -0,0 +1,99 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [{
+            "id": "id",
+            "secure": 1,
+            "bidfloor": 0.01,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "key": "test"
+              }
+            }
+          }],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": ["IAB12"],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 400,
+        "body": "The Key has a different ad format"
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad Request. \"The Key has a different ad format\"",
+      "comparison": "literal"
+    }
+  ],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/supplemental/status-503.json b/adapters/sa_lunamedia/salunamediatest/supplemental/status-503.json
new file mode 100644
index 00000000..2590418a
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/supplemental/status-503.json
@@ -0,0 +1,98 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [{
+            "id": "id",
+            "secure": 1,
+            "bidfloor": 0.01,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "key": "test"
+              }
+            }
+          }],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": ["IAB12"],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 503
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bidder unavailable. Please contact the bidder support.",
+      "comparison": "literal"
+    }
+  ],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/salunamediatest/supplemental/unexpected-status.json b/adapters/sa_lunamedia/salunamediatest/supplemental/unexpected-status.json
new file mode 100644
index 00000000..a54737ca
--- /dev/null
+++ b/adapters/sa_lunamedia/salunamediatest/supplemental/unexpected-status.json
@@ -0,0 +1,99 @@
+{
+  "mockBidRequest": {
+    "id": "id",
+    "imp": [{
+      "id": "id",
+      "secure": 1,
+      "bidfloor": 0.01,
+      "bidfloorcur": "USD",
+      "banner": {
+        "w": 300,
+        "h": 250
+      },
+      "ext": {
+        "bidder": {
+          "key": "test"
+        }
+      }
+    }],
+    "device": {
+      "ua": "UA",
+      "ip": "123.3.4.123"
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "user": {
+      "id": "userid"
+    },
+    "site": {
+      "id": "id",
+      "domain": "test,com",
+      "cat": ["IAB12"],
+      "publisher": {
+        "id": "pubid"
+      }
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://test.com/pserver",
+        "body": {
+          "id": "id",
+          "imp": [{
+            "id": "id",
+            "secure": 1,
+            "bidfloor": 0.01,
+            "bidfloorcur": "USD",
+            "banner": {
+              "w": 300,
+              "h": 250
+            },
+            "ext": {
+              "bidder": {
+                "key": "test"
+              }
+            }
+          }],
+          "device": {
+            "ua": "UA",
+            "ip": "123.3.4.123"
+          },
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "user": {
+            "id": "userid"
+          },
+          "site": {
+            "id": "id",
+            "domain": "test,com",
+            "cat": ["IAB12"],
+            "publisher": {
+              "id": "pubid"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 403,
+        "body": "Access is denied"
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Status Code: [ 403 ] \"Access is denied\"",
+      "comparison": "literal"
+    }
+  ],
+
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/sa_lunamedia/usersync_test.go b/adapters/sa_lunamedia/usersync_test.go
new file mode 100644
index 00000000..e3820fbc
--- /dev/null
+++ b/adapters/sa_lunamedia/usersync_test.go
@@ -0,0 +1,33 @@
+package salunamedia
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/ccpa"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewSaLunamediaSyncer(t *testing.T) {
+	syncURL := "https://test.com/pserver?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ccpa={{.USPrivacy}}"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+	syncer := NewSaLunamediaSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "0",
+			Consent: "allGdpr",
+		},
+		CCPA: ccpa.Policy{
+			Consent: "1---",
+		},
+	})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "https://test.com/pserver?gdpr=0&gdpr_consent=allGdpr&ccpa=1---", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/currency/aggregate_conversions_test.go b/currency/aggregate_conversions_test.go
index 35ca51a1..773a596c 100644
--- a/currency/aggregate_conversions_test.go
+++ b/currency/aggregate_conversions_test.go
@@ -65,7 +65,7 @@ func TestGroupedGetRate(t *testing.T) {
 			},
 		},
 		{
-			expectedError: ConversionRateNotFound{"GBP", "EUR"},
+			expectedError: ConversionNotFoundError{FromCur: "GBP", ToCur: "EUR"},
 			testCases: []aTest{
 				{"Valid three-digit currency codes, but conversion rate not found", "GBP", "EUR", 0},
 			},
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index 079b9adb..61164bd7 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -32,7 +32,6 @@ func TestGoodAmpRequests(t *testing.T) {
 	goodRequests := map[string]json.RawMessage{
 		"1": json.RawMessage(validRequest(t, "aliased-buyeruids.json")),
 		"2": json.RawMessage(validRequest(t, "aliases.json")),
-		"4": json.RawMessage(validRequest(t, "digitrust.json")),
 		"5": json.RawMessage(validRequest(t, "gdpr-no-consentstring.json")),
 		"6": json.RawMessage(validRequest(t, "gdpr.json")),
 		"7": json.RawMessage(validRequest(t, "site.json")),
@@ -122,11 +121,6 @@ func TestAMPPageInfo(t *testing.T) {
 func TestGDPRConsent(t *testing.T) {
 	consent := "BOu5On0Ou5On0ADACHENAO7pqzAAppY"
 	existingConsent := "BONV8oqONXwgmADACHENAO7pqzAAppY"
-	digitrust := &openrtb_ext.ExtUserDigiTrust{
-		ID:   "anyDigitrustID",
-		KeyV: 1,
-		Pref: 0,
-	}
 
 	testCases := []struct {
 		description     string
@@ -165,12 +159,10 @@ func TestGDPRConsent(t *testing.T) {
 			description: "Overrides Existing Consent - With Sibling Data",
 			consent:     consent,
 			userExt: &openrtb_ext.ExtUser{
-				Consent:   existingConsent,
-				DigiTrust: digitrust,
+				Consent: existingConsent,
 			},
 			expectedUserExt: openrtb_ext.ExtUser{
-				Consent:   consent,
-				DigiTrust: digitrust,
+				Consent: consent,
 			},
 		},
 		{
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index deff0662..213af9a0 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -564,7 +564,7 @@ func TestMultiCurrencies(t *testing.T) {
 				{currency: "USD", price: 1.3 * 1.3050530256},
 			},
 			expectedBadCurrencyErrors: []error{
-				currency.ConversionRateNotFound{"JPY", "USD"},
+				currency.ConversionNotFoundError{FromCur: "JPY", ToCur: "USD"},
 			},
 			description: "Case 6 - Bidder respond with a mix of currencies and one unknown on all HTTP responses",
 		},
@@ -587,9 +587,9 @@ func TestMultiCurrencies(t *testing.T) {
 			},
 			expectedBids: []bid{},
 			expectedBadCurrencyErrors: []error{
-				currency.ConversionRateNotFound{"JPY", "USD"},
-				currency.ConversionRateNotFound{"BZD", "USD"},
-				currency.ConversionRateNotFound{"DKK", "USD"},
+				currency.ConversionNotFoundError{FromCur: "JPY", ToCur: "USD"},
+				currency.ConversionNotFoundError{FromCur: "BZD", ToCur: "USD"},
+				currency.ConversionNotFoundError{FromCur: "DKK", ToCur: "USD"},
 			},
 			description: "Case 7 - Bidder respond with currencies not having any rate on all HTTP responses",
 		},
@@ -720,9 +720,9 @@ func TestMultiCurrencies_RateConverterNotSet(t *testing.T) {
 			bidCurrency:       []string{"EUR", "EUR", "EUR"},
 			expectedBidsCount: 0,
 			expectedBadCurrencyErrors: []error{
-				currency.ConversionRateNotFound{"EUR", "USD"},
-				currency.ConversionRateNotFound{"EUR", "USD"},
-				currency.ConversionRateNotFound{"EUR", "USD"},
+				currency.ConversionNotFoundError{FromCur: "EUR", ToCur: "USD"},
+				currency.ConversionNotFoundError{FromCur: "EUR", ToCur: "USD"},
+				currency.ConversionNotFoundError{FromCur: "EUR", ToCur: "USD"},
 			},
 			description: "Case 2 - Bidder respond with the same currency (not default one) on all HTTP responses",
 		},
@@ -754,7 +754,7 @@ func TestMultiCurrencies_RateConverterNotSet(t *testing.T) {
 			bidCurrency:       []string{"EUR", "", "USD"},
 			expectedBidsCount: 2,
 			expectedBadCurrencyErrors: []error{
-				currency.ConversionRateNotFound{"EUR", "USD"},
+				currency.ConversionNotFoundError{FromCur: "EUR", ToCur: "USD"},
 			},
 			description: "Case 7 - Bidder responds with a mix of not set, non default currency and default currency in HTTP responses",
 		},
@@ -762,7 +762,7 @@ func TestMultiCurrencies_RateConverterNotSet(t *testing.T) {
 			bidCurrency:       []string{"GBP", "", "USD"},
 			expectedBidsCount: 2,
 			expectedBadCurrencyErrors: []error{
-				currency.ConversionRateNotFound{"GBP", "USD"},
+				currency.ConversionNotFoundError{FromCur: "GBP", ToCur: "USD"},
 			},
 			description: "Case 8 - Bidder responds with a mix of not set, non default currency and default currency in HTTP responses",
 		},
@@ -770,7 +770,7 @@ func TestMultiCurrencies_RateConverterNotSet(t *testing.T) {
 			bidCurrency:       []string{"GBP", "", ""},
 			expectedBidsCount: 2,
 			expectedBadCurrencyErrors: []error{
-				currency.ConversionRateNotFound{"GBP", "USD"},
+				currency.ConversionNotFoundError{FromCur: "GBP", ToCur: "USD"},
 			},
 			description: "Case 9 - Bidder responds with a mix of not set and empty currencies (default currency) in HTTP responses",
 		},
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 2d1306af..989e6707 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -31,6 +31,7 @@ import (
 
 	"github.com/buger/jsonparser"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"github.com/yudai/gojsondiff"
 	"github.com/yudai/gojsondiff/formatter"
 )
@@ -539,7 +540,7 @@ func TestTwoBiddersDebugDisabledAndEnabled(t *testing.T) {
 
 func TestOverrideWithCustomCurrency(t *testing.T) {
 
-	mockCurrencyClient := &mockCurrencyRatesClient{
+	mockCurrencyClient := &fakeCurrencyRatesHttpClient{
 		responseBody: `{"dataAsOf":"2018-09-12","conversions":{"USD":{"MXN":10.00}}}`,
 	}
 	mockCurrencyConverter := currency.NewRateConverter(
@@ -694,6 +695,72 @@ func TestOverrideWithCustomCurrency(t *testing.T) {
 	}
 }
 
+func TestAdapterCurrency(t *testing.T) {
+	fakeCurrencyClient := &fakeCurrencyRatesHttpClient{
+		responseBody: `{"dataAsOf":"2018-09-12","conversions":{"USD":{"MXN":10.00}}}`,
+	}
+	currencyConverter := currency.NewRateConverter(
+		fakeCurrencyClient,
+		"currency.fake.com",
+		24*time.Hour,
+	)
+	currencyConverter.Run()
+
+	// Initialize Mock Bidder
+	// - Response purposefully causes PBS-Core to stop processing the request, since this test is only
+	//   interested in the call to MakeRequests and nothing after.
+	mockBidder := &mockBidder{}
+	mockBidder.On("MakeRequests", mock.Anything, mock.Anything).Return([]*adapters.RequestData(nil), []error(nil))
+
+	// Initialize Real Exchange
+	e := exchange{
+		cache:             &wellBehavedCache{},
+		me:                &metricsConf.DummyMetricsEngine{},
+		gDPR:              gdpr.AlwaysAllow{},
+		currencyConverter: currencyConverter,
+		categoriesFetcher: nilCategoryFetcher{},
+		bidIDGenerator:    &mockBidIDGenerator{false, false},
+		adapterMap: map[openrtb_ext.BidderName]adaptedBidder{
+			openrtb_ext.BidderName("foo"): adaptBidder(mockBidder, nil, &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderName("foo"), nil),
+		},
+	}
+
+	// Define Bid Request
+	request := &openrtb2.BidRequest{
+		ID: "some-request-id",
+		Imp: []openrtb2.Imp{{
+			ID:     "some-impression-id",
+			Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}, {W: 300, H: 600}}},
+			Ext:    json.RawMessage(`{"foo": {"placementId": 1}}`),
+		}},
+		Site: &openrtb2.Site{
+			Page: "prebid.org",
+			Ext:  json.RawMessage(`{"amp":0}`),
+		},
+		Cur: []string{"USD"},
+		Ext: json.RawMessage(`{"prebid": {"currency": {"rates": {"USD": {"MXN": 20.00}}}}}`),
+	}
+
+	// Run Auction
+	auctionRequest := AuctionRequest{
+		BidRequest: request,
+		Account:    config.Account{},
+		UserSyncs:  &emptyUsersync{},
+	}
+	response, err := e.HoldAuction(context.Background(), auctionRequest, &DebugLog{})
+	assert.NoError(t, err)
+	assert.Equal(t, "some-request-id", response.ID, "Response ID")
+	assert.Empty(t, response.SeatBid, "Response Bids")
+	assert.Contains(t, string(response.Ext), `"errors":{"foo":[{"code":5,"message":"The adapter failed to generate any bid requests, but also failed to generate an error explaining why"}]}`, "Response Ext")
+
+	// Test Currency Converter Properly Passed To Adapter
+	if assert.NotNil(t, mockBidder.lastExtraRequestInfo, "Currency Conversion Argument") {
+		converted, err := mockBidder.lastExtraRequestInfo.ConvertCurrency(2.0, "USD", "MXN")
+		assert.NoError(t, err, "Currency Conversion Error")
+		assert.Equal(t, 40.0, converted, "Currency Conversion Response")
+	}
+}
+
 func TestGetAuctionCurrencyRates(t *testing.T) {
 
 	pbsRates := map[string]map[string]float64{
@@ -859,7 +926,7 @@ func TestGetAuctionCurrencyRates(t *testing.T) {
 		}
 
 		// Init mock currency conversion service
-		mockCurrencyClient := &mockCurrencyRatesClient{
+		mockCurrencyClient := &fakeCurrencyRatesHttpClient{
 			responseBody: `{"dataAsOf":"2018-09-12","conversions":` + string(jsonPbsRates) + `}`,
 		}
 		mockCurrencyConverter := currency.NewRateConverter(
@@ -1720,7 +1787,7 @@ func newRaceCheckingRequest(t *testing.T) *openrtb2.BidRequest {
 		User: &openrtb2.User{
 			ID:       "our-id",
 			BuyerUID: "their-id",
-			Ext:      json.RawMessage(`{"consent":"BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw","digitrust":{"id":"digi-id","keyv":1,"pref":1}}`),
+			Ext:      json.RawMessage(`{"consent":"BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw"}`),
 		},
 		Regs: &openrtb2.Regs{
 			COPPA: 1,
@@ -1882,7 +1949,7 @@ func TestPanicRecoveryHighLevel(t *testing.T) {
 		User: &openrtb2.User{
 			ID:       "our-id",
 			BuyerUID: "their-id",
-			Ext:      json.RawMessage(`{"consent":"BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw","digitrust":{"id":"digi-id","keyv":1,"pref":1}}`),
+			Ext:      json.RawMessage(`{"consent":"BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw"}`),
 		},
 		Imp: []openrtb2.Imp{{
 			ID: "some-imp-id",
@@ -3654,15 +3721,32 @@ func (nilCategoryFetcher) FetchCategories(ctx context.Context, primaryAdServer,
 	return "", nil
 }
 
-// mockCurrencyRatesClient is a simple http client mock returning a constant response body
-type mockCurrencyRatesClient struct {
+// fakeCurrencyRatesHttpClient is a simple http client mock returning a constant response body
+type fakeCurrencyRatesHttpClient struct {
 	responseBody string
 }
 
-func (m *mockCurrencyRatesClient) Do(req *http.Request) (*http.Response, error) {
+func (m *fakeCurrencyRatesHttpClient) Do(req *http.Request) (*http.Response, error) {
 	return &http.Response{
 		Status:     "200 OK",
 		StatusCode: http.StatusOK,
 		Body:       ioutil.NopCloser(strings.NewReader(m.responseBody)),
 	}, nil
 }
+
+type mockBidder struct {
+	mock.Mock
+	lastExtraRequestInfo *adapters.ExtraRequestInfo
+}
+
+func (m *mockBidder) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	m.lastExtraRequestInfo = reqInfo
+
+	args := m.Called(request, reqInfo)
+	return args.Get(0).([]*adapters.RequestData), args.Get(1).([]error)
+}
+
+func (m *mockBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	args := m.Called(internalRequest, externalRequest, response)
+	return args.Get(0).(*adapters.BidderResponse), args.Get(1).([]error)
+}
diff --git a/exchange/exchangetest/request-other-user-ext.json b/exchange/exchangetest/request-other-user-ext.json
index 9bd4c02f..f9fb3264 100644
--- a/exchange/exchangetest/request-other-user-ext.json
+++ b/exchange/exchangetest/request-other-user-ext.json
@@ -12,11 +12,6 @@
             "buyeruids": {
               "appnexus": "explicit-appnexus"
             }
-          },
-          "digitrust": {
-            "id": "digi-id",
-            "keyv": 1,
-            "pref": 2
           }
         }
       },
@@ -48,14 +43,7 @@
           },
           "user": {
             "id": "foo",
-            "buyeruid": "explicit-appnexus",
-            "ext": {
-              "digitrust": {
-                "id": "digi-id",
-                "keyv": 1,
-                "pref": 2
-              }
-            }
+            "buyeruid": "explicit-appnexus"
           },
           "imp": [
             {
diff --git a/exchange/exchangetest/request-user-no-prebid.json b/exchange/exchangetest/request-user-no-prebid.json
index bb36ba8a..aae11606 100644
--- a/exchange/exchangetest/request-user-no-prebid.json
+++ b/exchange/exchangetest/request-user-no-prebid.json
@@ -8,11 +8,6 @@
       "user": {
         "id": "foo",
         "ext": {
-          "digitrust": {
-            "id": "digi-id",
-            "keyv": 1,
-            "pref": 2
-          }
         }
       },
       "imp": [
@@ -45,11 +40,6 @@
             "id": "foo",
             "buyeruid": "implicit-appnexus",
             "ext": {
-              "digitrust": {
-                "id": "digi-id",
-                "keyv": 1,
-                "pref": 2
-              }
             }
           },
           "imp": [
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 5a281f9a..5a9fa187 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -1788,7 +1788,7 @@ func newAdapterAliasBidRequest(t *testing.T) *openrtb2.BidRequest {
 		User: &openrtb2.User{
 			ID:       "our-id",
 			BuyerUID: "their-id",
-			Ext:      json.RawMessage(`{"consent":"BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw","digitrust":{"id":"digi-id","keyv":1,"pref":1}}`),
+			Ext:      json.RawMessage(`{"consent":"BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw"}`),
 		},
 		Regs: &openrtb2.Regs{
 			Ext: json.RawMessage(`{"gdpr":1}`),
@@ -1833,7 +1833,7 @@ func newBidRequest(t *testing.T) *openrtb2.BidRequest {
 			ID:       "our-id",
 			BuyerUID: "their-id",
 			Yob:      1982,
-			Ext:      json.RawMessage(`{"digitrust":{"id":"digi-id","keyv":1,"pref":1}}`),
+			Ext:      json.RawMessage(`{}`),
 		},
 		Imp: []openrtb2.Imp{{
 			ID: "some-imp-id",
diff --git a/privacy/scrubber_test.go b/privacy/scrubber_test.go
index 9207315f..1198d0bb 100644
--- a/privacy/scrubber_test.go
+++ b/privacy/scrubber_test.go
@@ -202,7 +202,7 @@ func TestScrubUser(t *testing.T) {
 		BuyerUID: "anyBuyerUID",
 		Yob:      42,
 		Gender:   "anyGender",
-		Ext:      json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+		Ext:      json.RawMessage(`{}`),
 		Geo: &openrtb2.Geo{
 			Lat:   123.456,
 			Lon:   678.89,
@@ -327,7 +327,7 @@ func TestScrubUser(t *testing.T) {
 				BuyerUID: "anyBuyerUID",
 				Yob:      42,
 				Gender:   "anyGender",
-				Ext:      json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+				Ext:      json.RawMessage(`{}`),
 				Geo:      &openrtb2.Geo{},
 			},
 			scrubUser: ScrubStrategyUserNone,
@@ -340,7 +340,7 @@ func TestScrubUser(t *testing.T) {
 				BuyerUID: "anyBuyerUID",
 				Yob:      42,
 				Gender:   "anyGender",
-				Ext:      json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+				Ext:      json.RawMessage(`{}`),
 				Geo: &openrtb2.Geo{
 					Lat:   123.46,
 					Lon:   678.89,
@@ -359,7 +359,7 @@ func TestScrubUser(t *testing.T) {
 				BuyerUID: "anyBuyerUID",
 				Yob:      42,
 				Gender:   "anyGender",
-				Ext:      json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+				Ext:      json.RawMessage(`{}`),
 				Geo: &openrtb2.Geo{
 					Lat:   123.456,
 					Lon:   678.89,
@@ -586,18 +586,18 @@ func TestScrubUserExtIDs(t *testing.T) {
 			expected:    json.RawMessage(`{"anyExisting":42}}`),
 		},
 		{
-			description: "Remove eids + digitrust",
-			userExt:     json.RawMessage(`{"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}],"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+			description: "Remove eids",
+			userExt:     json.RawMessage(`{"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
 			expected:    json.RawMessage(`{}`),
 		},
 		{
-			description: "Remove eids + digitrust - With Other Data",
-			userExt:     json.RawMessage(`{"anyExisting":42,"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}],"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+			description: "Remove eids - With Other Data",
+			userExt:     json.RawMessage(`{"anyExisting":42,"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
 			expected:    json.RawMessage(`{"anyExisting":42}`),
 		},
 		{
-			description: "Remove eids + digitrust - With Other Nested Data",
-			userExt:     json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}],"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
+			description: "Remove eids - With Other Nested Data",
+			userExt:     json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
 			expected:    json.RawMessage(`{"anyExisting":{"existing":42}}`),
 		},
 		{
@@ -620,21 +620,6 @@ func TestScrubUserExtIDs(t *testing.T) {
 			userExt:     json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
 			expected:    json.RawMessage(`{"anyExisting":{"existing":42}}`),
 		},
-		{
-			description: "Remove digitrust Only",
-			userExt:     json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
-			expected:    json.RawMessage(`{}`),
-		},
-		{
-			description: "Remove digitrust Only - With Other Data",
-			userExt:     json.RawMessage(`{"anyExisting":42,"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
-			expected:    json.RawMessage(`{"anyExisting":42}`),
-		},
-		{
-			description: "Remove digitrust Only - With Other Nested Data",
-			userExt:     json.RawMessage(`{"anyExisting":{"existing":42},"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
-			expected:    json.RawMessage(`{"anyExisting":{"existing":42}}`),
-		},
 	}
 
 	for _, test := range testCases {
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index 0cea346e..35ceb1b7 100644
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -37,6 +37,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderBeachfront):       syncConfig,
 			string(openrtb_ext.BidderBeintoo):          syncConfig,
 			string(openrtb_ext.BidderBetween):          syncConfig,
+			string(openrtb_ext.BidderBidmyadz):         syncConfig,
 			string(openrtb_ext.BidderBmtm):             syncConfig,
 			string(openrtb_ext.BidderBrightroll):       syncConfig,
 			string(openrtb_ext.BidderColossus):         syncConfig,
@@ -57,6 +58,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderGrid):             syncConfig,
 			string(openrtb_ext.BidderGumGum):           syncConfig,
 			string(openrtb_ext.BidderImprovedigital):   syncConfig,
+			string(openrtb_ext.BidderInMobi):           syncConfig,
 			string(openrtb_ext.BidderInvibes):          syncConfig,
 			string(openrtb_ext.BidderIx):               syncConfig,
 			string(openrtb_ext.BidderJixie):            syncConfig,
@@ -64,6 +66,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderLockerDome):       syncConfig,
 			string(openrtb_ext.BidderLogicad):          syncConfig,
 			string(openrtb_ext.BidderLunaMedia):        syncConfig,
+			string(openrtb_ext.BidderSaLunaMedia):      syncConfig,
 			string(openrtb_ext.BidderMarsmedia):        syncConfig,
 			string(openrtb_ext.BidderMediafuse):        syncConfig,
 			string(openrtb_ext.BidderMgid):             syncConfig,
@@ -118,7 +121,6 @@ func TestNewSyncerMap(t *testing.T) {
 		openrtb_ext.BidderBidsCube:          true,
 		openrtb_ext.BidderEpom:              true,
 		openrtb_ext.BidderDecenterAds:       true,
-		openrtb_ext.BidderInMobi:            true,
 		openrtb_ext.BidderInteractiveoffers: true,
 		openrtb_ext.BidderKayzen:            true,
 		openrtb_ext.BidderKidoz:             true,