Repository: prebid/prebid-server
Pull request #1564 (2020-11-03 18:04:10)

Add account/ host GDPR enabled flags & account per request type GDPR enabled flags
The order of precedence for determining whether GDPR is enabled is:
1) Use account-level request type setting if specified
2) Use account-level general setting if specified
3) Use host-level general setting

Related issue: https://github.com/prebid/prebid-server/issues/1323


Patch:
diff --git a/adapters/33across/33across.go b/adapters/33across/33across.go
index 5c1b31ee..40099a20 100644
--- a/adapters/33across/33across.go
+++ b/adapters/33across/33across.go
@@ -24,6 +24,14 @@ type ext struct {
 	Zoneid string `json:"zoneid,omitempty"`
 }
 
+type bidExt struct {
+	Ttx bidTtxExt `json:"ttx,omitempty"`
+}
+
+type bidTtxExt struct {
+	MediaType string `json:mediaType,omitempty`
+}
+
 // MakeRequests create the object for TTX Reqeust.
 func (a *TtxAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 	var errs []error
@@ -49,6 +57,14 @@ func (a *TtxAdapter) makeRequest(request *openrtb.BidRequest) (*adapters.Request
 		errs = append(errs, err)
 	}
 
+	if reqCopy.Imp[0].Banner == nil && reqCopy.Imp[0].Video == nil {
+		errs = append(errs, &errortypes.BadInput{
+			Message: "At least one of [banner, video] formats must be defined in Imp. None found",
+		})
+
+		return nil, errs
+	}
+
 	// Last Step
 	reqJSON, err := json.Marshal(reqCopy)
 	if err != nil {
@@ -104,6 +120,19 @@ func preprocess(request *openrtb.BidRequest) error {
 	siteCopy.ID = ttxExt.SiteId
 	request.Site = &siteCopy
 
+	// Validate Video if it exists
+	if imp.Video != nil {
+		videoCopy, err := validateVideoParams(imp.Video, impExt.Ttx.Prod)
+
+		imp.Video = videoCopy
+
+		if err != nil {
+			return &errortypes.BadInput{
+				Message: err.Error(),
+			}
+		}
+	}
+
 	return nil
 }
 
@@ -135,9 +164,18 @@ func (a *TtxAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalReque
 
 	for _, sb := range bidResp.SeatBid {
 		for i := range sb.Bid {
+			var bidExt bidExt
+			var bidType openrtb_ext.BidType
+
+			if err := json.Unmarshal(sb.Bid[i].Ext, &bidExt); err != nil {
+				bidType = openrtb_ext.BidTypeBanner
+			} else {
+				bidType = getBidType(bidExt)
+			}
+
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
 				Bid:     &sb.Bid[i],
-				BidType: "banner",
+				BidType: bidType,
 			})
 		}
 	}
@@ -145,6 +183,43 @@ func (a *TtxAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalReque
 
 }
 
+func validateVideoParams(video *openrtb.Video, prod string) (*openrtb.Video, error) {
+	videoCopy := video
+	if videoCopy.W == 0 ||
+		videoCopy.H == 0 ||
+		videoCopy.Protocols == nil ||
+		videoCopy.MIMEs == nil ||
+		videoCopy.PlaybackMethod == nil {
+
+		return nil, &errortypes.BadInput{
+			Message: "One or more invalid or missing video field(s) w, h, protocols, mimes, playbackmethod",
+		}
+	}
+
+	if videoCopy.Placement == 0 {
+		videoCopy.Placement = 2
+	}
+
+	if prod == "instream" {
+		videoCopy.Placement = 1
+
+		if videoCopy.StartDelay == nil {
+			videoCopy.StartDelay = openrtb.StartDelay.Ptr(0)
+		}
+	}
+
+	return videoCopy, nil
+}
+
+func getBidType(ext bidExt) openrtb_ext.BidType {
+	if ext.Ttx.MediaType == "video" {
+		return openrtb_ext.BidTypeVideo
+	}
+
+	return openrtb_ext.BidTypeBanner
+}
+
+// New33AcrossBidder configures bidder endpoint
 func New33AcrossBidder(endpoint string) *TtxAdapter {
 	return &TtxAdapter{
 		endpoint: endpoint,
diff --git a/adapters/33across/33across/exemplary/simple-banner.json b/adapters/33across/33acrosstest/exemplary/simple-banner.json
similarity index 85%
rename from adapters/33across/33across/exemplary/simple-banner.json
rename to adapters/33across/33acrosstest/exemplary/simple-banner.json
index 074badad..d8c215c0 100644
--- a/adapters/33across/33across/exemplary/simple-banner.json
+++ b/adapters/33across/33acrosstest/exemplary/simple-banner.json
@@ -56,7 +56,12 @@
                 "adm": "some-test-ad",
                 "crid": "crid_10",
                 "h": 90,
-                "w": 728
+                "w": 728,
+                "ext": {
+                  "ttx": {
+                    "mediaType": "banner"
+                  }
+                }
               }]
             }
           ],
@@ -78,7 +83,12 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 728,
-            "h": 90
+            "h": 90,
+            "ext": {
+              "ttx": {
+                "mediaType": "banner"
+              }
+            }
           },
           "type": "banner"
         }
diff --git a/adapters/adhese/adhese.go b/adapters/adhese/adhese.go
index 10aaf6e8..3938b161 100644
--- a/adapters/adhese/adhese.go
+++ b/adapters/adhese/adhese.go
@@ -73,6 +73,13 @@ func extractRefererParameter(request *openrtb.BidRequest) string {
 	return ""
 }
 
+func extractIfaParameter(request *openrtb.BidRequest) string {
+	if request.Device != nil && request.Device.IFA != "" {
+		return "/xz" + url.QueryEscape(request.Device.IFA)
+	}
+	return ""
+}
+
 func (a *AdheseAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 	errs := make([]error, 0, len(request.Imp))
 
@@ -106,12 +113,13 @@ func (a *AdheseAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapt
 		errs = append(errs, WrapReqError("Could not compose url from template and request account val: "+err.Error()))
 		return nil, errs
 	}
-	complete_url := fmt.Sprintf("%s%s%s%s%s",
+	complete_url := fmt.Sprintf("%s%s%s%s%s%s",
 		host,
 		extractSlotParameter(params),
 		extractTargetParameters(params),
 		extractGdprParameter(request),
-		extractRefererParameter(request))
+		extractRefererParameter(request),
+		extractIfaParameter(request))
 
 	return []*adapters.RequestData{{
 		Method: "GET",
diff --git a/adapters/adoppler/adoppler.go b/adapters/adoppler/adoppler.go
index c604bfea..77eedec1 100644
--- a/adapters/adoppler/adoppler.go
+++ b/adapters/adoppler/adoppler.go
@@ -6,13 +6,18 @@ import (
 	"fmt"
 	"net/http"
 	"net/url"
+	"text/template"
 
+	"github.com/golang/glog"
 	"github.com/mxmCherry/openrtb"
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/macros"
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
+const DefaultClient = "app"
+
 var bidHeaders http.Header = map[string][]string{
 	"Accept":            {"application/json"},
 	"Content-Type":      {"application/json;charset=utf-8"},
@@ -28,11 +33,17 @@ type adsImpExt struct {
 }
 
 type AdopplerAdapter struct {
-	endpoint string
+	endpoint *template.Template
 }
 
 func NewAdopplerBidder(endpoint string) *AdopplerAdapter {
-	return &AdopplerAdapter{endpoint}
+	t, err := template.New("endpoint").Parse(endpoint)
+	if err != nil {
+		glog.Fatalf("Unable to parse endpoint url template: %s", err)
+		return nil
+	}
+
+	return &AdopplerAdapter{t}
 }
 
 func (ads *AdopplerAdapter) MakeRequests(
@@ -65,8 +76,13 @@ func (ads *AdopplerAdapter) MakeRequests(
 			continue
 		}
 
-		uri := fmt.Sprintf("%s/processHeaderBid/%s",
-			ads.endpoint, url.PathEscape(ext.AdUnit))
+		uri, err := ads.bidUri(ext)
+		if err != nil {
+			e := fmt.Sprintf("Unable to build bid URI: %s",
+				err.Error())
+			errs = append(errs, &errortypes.BadInput{e})
+			continue
+		}
 		data := &adapters.RequestData{
 			Method:  "POST",
 			Uri:     uri,
@@ -172,6 +188,18 @@ func (ads *AdopplerAdapter) MakeBids(
 	return adsResp, nil
 }
 
+func (ads *AdopplerAdapter) bidUri(ext *openrtb_ext.ExtImpAdoppler) (string, error) {
+	params := macros.EndpointTemplateParams{}
+	params.AdUnit = url.PathEscape(ext.AdUnit)
+	if ext.Client == "" {
+		params.AccountID = DefaultClient
+	} else {
+		params.AccountID = url.PathEscape(ext.Client)
+	}
+
+	return macros.ResolveMacros(*ads.endpoint, params)
+}
+
 func unmarshalExt(ext json.RawMessage) (*openrtb_ext.ExtImpAdoppler, error) {
 	var bext adapters.ExtImpBidder
 	err := json.Unmarshal(ext, &bext)
diff --git a/adapters/adpone/usersync.go b/adapters/adpone/usersync.go
index 480ecb82..67d4c998 100644
--- a/adapters/adpone/usersync.go
+++ b/adapters/adpone/usersync.go
@@ -7,7 +7,7 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const adponeGDPRVendorID = uint16(16)
+const adponeGDPRVendorID = uint16(799)
 const adponeFamilyName = "adpone"
 
 func NewadponeSyncer(urlTemplate *template.Template) usersync.Usersyncer {
diff --git a/adapters/adtelligent/usersync.go b/adapters/adtelligent/usersync.go
index cda3b62a..087b5bdd 100644
--- a/adapters/adtelligent/usersync.go
+++ b/adapters/adtelligent/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAdtelligentSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adtelligent", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adtelligent", 410, temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/amx/amx.go b/adapters/amx/amx.go
new file mode 100644
index 00000000..f46cbb2c
--- /dev/null
+++ b/adapters/amx/amx.go
@@ -0,0 +1,210 @@
+package amx
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+
+	"github.com/golang/glog"
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+const vastImpressionFormat = "<Impression><![CDATA[%s]]></Impression>"
+const vastSearchPoint = "</Impression>"
+const nbrHeaderName = "x-nbr"
+const adapterVersion = "pbs1.0"
+
+// AMXAdapter is the AMX bid adapter
+type AMXAdapter struct {
+	endpoint string
+}
+
+// NewAMXBidder creates an AMXAdapter
+func NewAMXBidder(endpoint string) *AMXAdapter {
+	endpointURL, err := url.Parse(endpoint)
+	if err != nil {
+		glog.Fatalf("invalid endpoint provided to AMX: %s, error: %v", endpoint, err)
+		return nil
+	}
+
+	qs, err := url.ParseQuery(endpointURL.RawQuery)
+	if err != nil {
+		glog.Fatalf("invalid query parameters in the endpoint: %s, error: %v", endpointURL.RawQuery, err)
+		return nil
+	}
+
+	qs.Add("v", adapterVersion)
+	endpointURL.RawQuery = qs.Encode()
+
+	return &AMXAdapter{endpoint: endpointURL.String()}
+}
+
+type amxExt struct {
+	Bidder openrtb_ext.ExtImpAMX `json:"bidder"`
+}
+
+func ensurePublisherWithID(pub *openrtb.Publisher, publisherID string) openrtb.Publisher {
+	if pub == nil {
+		return openrtb.Publisher{ID: publisherID}
+	}
+
+	pubCopy := *pub
+	pubCopy.ID = publisherID
+	return pubCopy
+}
+
+// MakeRequests creates AMX adapter requests
+func (adapter *AMXAdapter) MakeRequests(request *openrtb.BidRequest, req *adapters.ExtraRequestInfo) (reqsBidder []*adapters.RequestData, errs []error) {
+	reqCopy := *request
+
+	var publisherID string
+	for idx, imp := range reqCopy.Imp {
+		var params amxExt
+		if err := json.Unmarshal(imp.Ext, &params); err == nil {
+			if params.Bidder.TagID != "" {
+				publisherID = params.Bidder.TagID
+			}
+
+			// if it has an adUnitId, set as the tagid
+			if params.Bidder.AdUnitID != "" {
+				imp.TagID = params.Bidder.AdUnitID
+				reqCopy.Imp[idx] = imp
+			}
+		}
+	}
+
+	if publisherID != "" {
+		if reqCopy.App != nil {
+			publisher := ensurePublisherWithID(reqCopy.App.Publisher, publisherID)
+			appCopy := *request.App
+			appCopy.Publisher = &publisher
+			reqCopy.App = &appCopy
+		}
+		if reqCopy.Site != nil {
+			publisher := ensurePublisherWithID(reqCopy.Site.Publisher, publisherID)
+			siteCopy := *request.Site
+			siteCopy.Publisher = &publisher
+			reqCopy.Site = &siteCopy
+		}
+	}
+
+	encoded, err := json.Marshal(reqCopy)
+	if err != nil {
+		errs = append(errs, err)
+		return nil, errs
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+
+	reqBidder := &adapters.RequestData{
+		Method:  "POST",
+		Uri:     adapter.endpoint,
+		Body:    encoded,
+		Headers: headers,
+	}
+	reqsBidder = append(reqsBidder, reqBidder)
+	return
+}
+
+type amxBidExt struct {
+	Himp       []string `json:"himp,omitempty"`
+	StartDelay *int     `json:"startdelay,omitempty"`
+}
+
+// MakeBids will parse the bids from the AMX server
+func (adapter *AMXAdapter) MakeBids(request *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var errs []error
+
+	if http.StatusNoContent == response.StatusCode {
+		return nil, nil
+	}
+
+	if http.StatusBadRequest == response.StatusCode {
+		internalNBR := response.Headers.Get(nbrHeaderName)
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Invalid Request: 400. Error Code: %s", internalNBR),
+		}}
+	}
+
+	if http.StatusOK != response.StatusCode {
+		internalNBR := response.Headers.Get(nbrHeaderName)
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected response: %d. Error Code: %s", response.StatusCode, internalNBR),
+		}}
+	}
+
+	var bidResp openrtb.BidResponse
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(5)
+
+	for _, sb := range bidResp.SeatBid {
+		for _, bid := range sb.Bid {
+			bidExt, bidExtErr := getBidExt(bid.Ext)
+			if bidExtErr != nil {
+				errs = append(errs, bidExtErr)
+				continue
+			}
+
+			bidType := getMediaTypeForBid(bidExt)
+			b := &adapters.TypedBid{
+				Bid:     &bid,
+				BidType: bidType,
+			}
+			if b.BidType == openrtb_ext.BidTypeVideo {
+				b.Bid.AdM = interpolateImpressions(bid, bidExt)
+				// remove the NURL so a client/player doesn't fire it twice
+				b.Bid.NURL = ""
+			}
+			bidResponse.Bids = append(bidResponse.Bids, b)
+		}
+	}
+	return bidResponse, errs
+
+}
+
+func getBidExt(ext json.RawMessage) (amxBidExt, error) {
+	if len(ext) == 0 {
+		return amxBidExt{}, nil
+	}
+
+	var bidExt amxBidExt
+	err := json.Unmarshal(ext, &bidExt)
+	return bidExt, err
+}
+
+func getMediaTypeForBid(bidExt amxBidExt) openrtb_ext.BidType {
+	if bidExt.StartDelay != nil {
+		return openrtb_ext.BidTypeVideo
+	}
+
+	return openrtb_ext.BidTypeBanner
+}
+
+func pixelToImpression(pixel string) string {
+	return fmt.Sprintf(vastImpressionFormat, pixel)
+}
+
+func interpolateImpressions(bid openrtb.Bid, ext amxBidExt) string {
+	var buffer strings.Builder
+	if bid.NURL != "" {
+		buffer.WriteString(pixelToImpression(bid.NURL))
+	}
+
+	for _, impPixel := range ext.Himp {
+		if impPixel != "" {
+			buffer.WriteString(pixelToImpression(impPixel))
+		}
+	}
+
+	results := strings.Replace(bid.AdM, vastSearchPoint, vastSearchPoint+buffer.String(), 1)
+	return results
+}
diff --git a/adapters/amx/usersync.go b/adapters/amx/usersync.go
new file mode 100644
index 00000000..28e6ac0e
--- /dev/null
+++ b/adapters/amx/usersync.go
@@ -0,0 +1,13 @@
+package amx
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+// NewAMXSyncer produces an AMX RTB usersyncer
+func NewAMXSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("amx", 737, temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/datablocks/usersync.go b/adapters/datablocks/usersync.go
index c8ec92aa..2b47b259 100644
--- a/adapters/datablocks/usersync.go
+++ b/adapters/datablocks/usersync.go
@@ -7,8 +7,8 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const datablocksGDPRVendorID = uint16(14)
+const datablocksGDPRVendorID = uint16(0)
 
 func NewDatablocksSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("datablocks", 14, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("datablocks", datablocksGDPRVendorID, temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/dmx/dmx.go b/adapters/dmx/dmx.go
index de33bd39..dfb97f33 100644
--- a/adapters/dmx/dmx.go
+++ b/adapters/dmx/dmx.go
@@ -4,13 +4,14 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+
 	"github.com/mxmCherry/openrtb"
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/errortypes"
 	"github.com/prebid/prebid-server/openrtb_ext"
-	"net/http"
-	"net/url"
-	"strings"
 )
 
 type DmxAdapter struct {
diff --git a/adapters/eplanning/usersync.go b/adapters/eplanning/usersync.go
index 252c106a..faa7fa82 100644
--- a/adapters/eplanning/usersync.go
+++ b/adapters/eplanning/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewEPlanningSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("eplanning", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("eplanning", 90, temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/nobid/nobid.go b/adapters/nobid/nobid.go
new file mode 100644
index 00000000..05bcf02f
--- /dev/null
+++ b/adapters/nobid/nobid.go
@@ -0,0 +1,122 @@
+package nobid
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// NoBidAdapter - NoBid Adapter definition
+type NoBidAdapter struct {
+	endpoint string
+}
+
+// NewNoBidBidder Initializes the Bidder
+func NewNoBidBidder(endpoint string) *NoBidAdapter {
+	return &NoBidAdapter{
+		endpoint: endpoint,
+	}
+}
+
+// MakeRequests Makes the OpenRTB request payload
+func (a *NoBidAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+
+	if len(request.Imp) == 0 {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("No Imps in Bid Request"),
+		}}
+	}
+
+	data, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+
+	return []*adapters.RequestData{{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    data,
+		Headers: headers,
+	}}, []error{}
+}
+
+// MakeBids makes the bids
+func (a *NoBidAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if response.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	var bidResp openrtb.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	count := getBidCount(bidResp)
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(count)
+
+	var errs []error
+
+	for _, sb := range bidResp.SeatBid {
+		for i := range sb.Bid {
+			bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					Bid:     &sb.Bid[i],
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+	return bidResponse, errs
+}
+
+func getBidCount(bidResponse openrtb.BidResponse) int {
+	c := 0
+	for _, sb := range bidResponse.SeatBid {
+		c = c + len(sb.Bid)
+	}
+	return c
+}
+
+func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType, error) {
+	mediaType := openrtb_ext.BidTypeBanner
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner == nil && imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			}
+			return mediaType, nil
+		}
+	}
+
+	// This shouldnt happen. Lets handle it just incase by returning an error.
+	return "", &errortypes.BadInput{
+		Message: fmt.Sprintf("Failed to find impression \"%s\"", impID),
+	}
+}
diff --git a/adapters/nobid/usersync.go b/adapters/nobid/usersync.go
new file mode 100644
index 00000000..c21413f5
--- /dev/null
+++ b/adapters/nobid/usersync.go
@@ -0,0 +1,12 @@
+package nobid
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewNoBidSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("nobid", 816, temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/silvermob/silvermob.go b/adapters/silvermob/silvermob.go
new file mode 100644
index 00000000..be7a1762
--- /dev/null
+++ b/adapters/silvermob/silvermob.go
@@ -0,0 +1,188 @@
+package silvermob
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/golang/glog"
+	"net/http"
+	"text/template"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/macros"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type SilverMobAdapter struct {
+	endpoint template.Template
+}
+
+func NewSilverMobBidder(endpointTemplate string) *SilverMobAdapter {
+	template, err := template.New("endpointTemplate").Parse(endpointTemplate)
+	if err != nil {
+		glog.Fatal("Unable to parse endpoint url template")
+		return nil
+	}
+	return &SilverMobAdapter{endpoint: *template}
+}
+
+func GetHeaders(request *openrtb.BidRequest) *http.Header {
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("X-Openrtb-Version", "2.5")
+
+	if request.Device != nil {
+		if len(request.Device.UA) > 0 {
+			headers.Add("User-Agent", request.Device.UA)
+		}
+
+		if len(request.Device.IPv6) > 0 {
+			headers.Add("X-Forwarded-For", request.Device.IPv6)
+		}
+
+		if len(request.Device.IP) > 0 {
+			headers.Add("X-Forwarded-For", request.Device.IP)
+		}
+	}
+
+	return &headers
+}
+
+func (a *SilverMobAdapter) MakeRequests(
+	openRTBRequest *openrtb.BidRequest,
+	reqInfo *adapters.ExtraRequestInfo,
+) (
+	[]*adapters.RequestData,
+	[]error,
+) {
+	requestCopy := *openRTBRequest
+	impCount := len(openRTBRequest.Imp)
+	requestData := make([]*adapters.RequestData, 0, impCount)
+	errs := []error{}
+
+	var err error
+
+	for _, imp := range openRTBRequest.Imp {
+		var silvermobExt *openrtb_ext.ExtSilverMob
+
+		silvermobExt, err = a.getImpressionExt(&imp)
+
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		url, err := a.buildEndpointURL(silvermobExt)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		requestCopy.Imp = []openrtb.Imp{imp}
+		reqJSON, err := json.Marshal(requestCopy)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		reqData := &adapters.RequestData{
+			Method:  http.MethodPost,
+			Body:    reqJSON,
+			Uri:     url,
+			Headers: *GetHeaders(&requestCopy),
+		}
+
+		requestData = append(requestData, reqData)
+	}
+
+	return requestData, errs
+}
+
+func (a *SilverMobAdapter) getImpressionExt(imp *openrtb.Imp) (*openrtb_ext.ExtSilverMob, error) {
+	var bidderExt adapters.ExtImpBidder
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: fmt.Sprintf("error unmarshaling imp.ext: %s", err.Error()),
+		}
+	}
+	var silvermobExt openrtb_ext.ExtSilverMob
+	if err := json.Unmarshal(bidderExt.Bidder, &silvermobExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: fmt.Sprintf("error unmarshaling imp.ext.bidder: %s", err.Error()),
+		}
+	}
+	return &silvermobExt, nil
+}
+
+func (a *SilverMobAdapter) buildEndpointURL(params *openrtb_ext.ExtSilverMob) (string, error) {
+	endpointParams := macros.EndpointTemplateParams{ZoneID: params.ZoneID, Host: params.Host}
+	return macros.ResolveMacros(a.endpoint, endpointParams)
+}
+
+func (a *SilverMobAdapter) MakeBids(
+	openRTBRequest *openrtb.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 status code: %d. Run with request.debug = 1 for more info", bidderRawResponse.StatusCode),
+		}}
+	}
+
+	if bidderRawResponse.StatusCode != http.StatusOK {
+		return nil, []error{fmt.Errorf("Unexpected status code: %d. Run with request.debug = 1 for more info", bidderRawResponse.StatusCode)}
+	}
+
+	responseBody := bidderRawResponse.Body
+	var bidResp openrtb.BidResponse
+	if err := json.Unmarshal(responseBody, &bidResp); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Error unmarshaling server Response: %s", err),
+		}}
+	}
+
+	if len(bidResp.SeatBid) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid array",
+		}}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+
+	for _, sb := range bidResp.SeatBid {
+		for _, bid := range sb.Bid {
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+				Bid:     &bid,
+				BidType: getMediaTypeForImp(bid.ImpID, openRTBRequest.Imp),
+			})
+		}
+	}
+
+	return bidResponse, nil
+}
+
+func getMediaTypeForImp(impId string, imps []openrtb.Imp) openrtb_ext.BidType {
+	mediaType := openrtb_ext.BidTypeBanner
+	for _, imp := range imps {
+		if imp.ID == impId {
+			if imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			} else if imp.Native != nil {
+				mediaType = openrtb_ext.BidTypeNative
+			}
+			return mediaType
+		}
+	}
+	return mediaType
+}
diff --git a/config/accounts.go b/config/accounts.go
index 162818eb..5ec818b8 100644
--- a/config/accounts.go
+++ b/config/accounts.go
@@ -1,9 +1,61 @@
 package config
 
+// IntegrationType enumerates the values of integrations Prebid Server can configure for an account
+type IntegrationType string
+
+// Possible values of integration types Prebid Server can configure for an account
+const (
+	IntegrationTypeAMP   IntegrationType = "amp"
+	IntegrationTypeApp   IntegrationType = "app"
+	IntegrationTypeVideo IntegrationType = "video"
+	IntegrationTypeWeb   IntegrationType = "web"
+)
+
 // Account represents a publisher account configuration
 type Account struct {
 	ID            string      `mapstructure:"id" json:"id"`
 	Disabled      bool        `mapstructure:"disabled" json:"disabled"`
 	CacheTTL      DefaultTTLs `mapstructure:"cache_ttl" json:"cache_ttl"`
 	EventsEnabled bool        `mapstructure:"events_enabled" json:"events_enabled"`
+	GDPR          AccountGDPR `mapstructure:"gdpr" json:"gdpr"`
+}
+
+// AccountGDPR represents account-specific GDPR configuration
+type AccountGDPR struct {
+	Enabled            *bool                  `mapstructure:"enabled" json:"enabled,omitempty"`
+	IntegrationEnabled AccountGDPRIntegration `mapstructure:"integration_enabled" json:"integration_enabled"`
+}
+
+// EnabledForIntegrationType indicates whether GDPR is turned on at the account level for the specified integration type
+// by using the integration type setting if defined or the general GDPR setting if defined; otherwise it returns nil
+func (a *AccountGDPR) EnabledForIntegrationType(integrationType IntegrationType) *bool {
+	var integrationEnabled *bool
+
+	switch integrationType {
+	case IntegrationTypeAMP:
+		integrationEnabled = a.IntegrationEnabled.AMP
+	case IntegrationTypeApp:
+		integrationEnabled = a.IntegrationEnabled.App
+	case IntegrationTypeVideo:
+		integrationEnabled = a.IntegrationEnabled.Video
+	case IntegrationTypeWeb:
+		integrationEnabled = a.IntegrationEnabled.Web
+	}
+
+	if integrationEnabled != nil {
+		return integrationEnabled
+	}
+	if a.Enabled != nil {
+		return a.Enabled
+	}
+
+	return nil
+}
+
+// AccountGDPRIntegration indicates whether GDPR is enabled for each integration type
+type AccountGDPRIntegration struct {
+	AMP   *bool `mapstructure:"amp" json:"amp,omitempty"`
+	App   *bool `mapstructure:"app" json:"app,omitempty"`
+	Video *bool `mapstructure:"video" json:"video,omitempty"`
+	Web   *bool `mapstructure:"web" json:"web,omitempty"`
 }
diff --git a/config/config.go b/config/config.go
index c08031c4..045aea3c 100755
--- a/config/config.go
+++ b/config/config.go
@@ -210,6 +210,7 @@ type Privacy struct {
 }
 
 type GDPR struct {
+	Enabled                 bool         `mapstructure:"enabled"`
 	HostVendorID            int          `mapstructure:"host_vendor_id"`
 	UsersyncIfAmbiguous     bool         `mapstructure:"usersync_if_ambiguous"`
 	Timeouts                GDPRTimeouts `mapstructure:"timeouts_ms"`
@@ -402,7 +403,11 @@ func validateAdapterEndpoint(endpoint string, adapterName string, errs configErr
 		return append(errs, fmt.Errorf("Invalid endpoint template: %s for adapter: %s. %v", endpoint, adapterName, err))
 	}
 	// Resolve macros (if any) in the endpoint URL
-	resolvedEndpoint, err := macros.ResolveMacros(*endpointTemplate, macros.EndpointTemplateParams{Host: dummyHost, PublisherID: dummyPublisherID, AccountID: dummyAccountID})
+	resolvedEndpoint, err := macros.ResolveMacros(*endpointTemplate, macros.EndpointTemplateParams{
+		Host:        dummyHost,
+		PublisherID: dummyPublisherID,
+		AccountID:   dummyAccountID,
+	})
 	if err != nil {
 		return append(errs, fmt.Errorf("Unable to resolve endpoint: %s for adapter: %s. %v", endpoint, adapterName, err))
 	}
@@ -708,6 +713,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	// openrtb_ext.BidderAdOcean doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdvangelists, "https://nep.advangelists.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadvangelists%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAJA, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Daja%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25s")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAMX, "https://prebid.a-mo.net/cchain/0?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Damx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAppnexus, "https://ib.adnxs.com/getuid?"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	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")
@@ -740,6 +746,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMgid, "https://cm.mgid.com/m?cdsp=363893&adu="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmgid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Bmuidn%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNanoInteractive, "https://ad.audiencemanager.de/hbs/cookie_sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dnanointeractive%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNinthDecimal, "https://rtb.ninthdecimal.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dninthdecimal%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNoBid, "https://ads.servenobid.com/getsync?tek=pbs&ver=1&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dnobid%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderOpenx, "https://rtb.openx.net/sync/prebid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dopenx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPubmatic, "https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&predirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPulsepoint, "https://bh.contextweb.com/rtset?pid=561205&ev=1&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpulsepoint%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25VGUID%25%25")
@@ -927,13 +934,14 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.adman.endpoint", "http://pub.admanmedia.com/?c=o&m=ortb")
 	v.SetDefault("adapters.admixer.endpoint", "http://inv-nets.admixer.net/pbs.aspx")
 	v.SetDefault("adapters.adocean.endpoint", "https://{{.Host}}")
-	v.SetDefault("adapters.adoppler.endpoint", "http://app.trustedmarketplace.io/ads")
+	v.SetDefault("adapters.adoppler.endpoint", "http://{{.AccountID}}.trustedmarketplace.io/ads/processHeaderBid/{{.AdUnit}}")
 	v.SetDefault("adapters.adpone.endpoint", "http://rtb.adpone.com/bid-request?src=prebid_server")
 	v.SetDefault("adapters.adprime.endpoint", "http://delta.adprime.com/?c=o&m=ortb")
 	v.SetDefault("adapters.adtarget.endpoint", "http://ghb.console.adtarget.com.tr/pbs/ortb")
 	v.SetDefault("adapters.adtelligent.endpoint", "http://ghb.adtelligent.com/pbs/ortb")
 	v.SetDefault("adapters.advangelists.endpoint", "http://nep.advangelists.com/xp/get?pubid={{.PublisherID}}")
 	v.SetDefault("adapters.aja.endpoint", "https://ad.as.amanad.adtdp.com/v1/bid/4")
+	v.SetDefault("adapters.amx.endpoint", "http://pbs.amxrtb.com/auction/openrtb")
 	v.SetDefault("adapters.applogy.endpoint", "http://rtb.applogy.com/v1/prebid")
 	v.SetDefault("adapters.appnexus.endpoint", "http://ib.adnxs.com/openrtb2") // Docs: https://wiki.appnexus.com/display/supply/Incoming+Bid+Request+from+SSPs
 	v.SetDefault("adapters.appnexus.platform_id", "5")
@@ -974,6 +982,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.mobilefuse.endpoint", "http://mfx-us-east.mobilefuse.com/openrtb?pub_id={{.PublisherID}}")
 	v.SetDefault("adapters.nanointeractive.endpoint", "https://ad.audiencemanager.de/hbs")
 	v.SetDefault("adapters.ninthdecimal.endpoint", "http://rtb.ninthdecimal.com/xp/get?pubid={{.PublisherID}}")
+	v.SetDefault("adapters.nobid.endpoint", "https://ads.servenobid.com/ortb_adreq?tek=pbs&ver=1")
 	v.SetDefault("adapters.openx.endpoint", "http://rtb.openx.net/prebid")
 	v.SetDefault("adapters.orbidder.endpoint", "https://orbidder.otto.de/openrtb2")
 	v.SetDefault("adapters.pubmatic.endpoint", "https://hbopenbid.pubmatic.com/translator?source=prebid-server")
@@ -984,6 +993,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.rubicon.disabled", true)
 	v.SetDefault("adapters.rubicon.endpoint", "http://exapi-us-east.rubiconproject.com/a/api/exchange.json")
 	v.SetDefault("adapters.sharethrough.endpoint", "http://btlr.sharethrough.com/FGMrCMMc/v1")
+	v.SetDefault("adapters.silvermob.endpoint", "http://{{.Host}}.silvermob.com/marketplace/api/dsp/bid/{{.ZoneID}}")
 	v.SetDefault("adapters.smaato.endpoint", "https://prebid.ad.smaato.net/oapi/prebid")
 	v.SetDefault("adapters.smartadserver.endpoint", "https://ssb-global.smartadserver.com")
 	v.SetDefault("adapters.smartrtb.endpoint", "http://market-east.smrtb.com/json/publisher/rtb?pubid={{.PublisherID}}")
@@ -1019,6 +1029,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("analytics.pubstack.buffers.count", 100)
 	v.SetDefault("analytics.pubstack.buffers.timeout", "900s")
 	v.SetDefault("amp_timeout_adjustment_ms", 0)
+	v.SetDefault("gdpr.enabled", true)
 	v.SetDefault("gdpr.host_vendor_id", 0)
 	v.SetDefault("gdpr.usersync_if_ambiguous", false)
 	v.SetDefault("gdpr.timeouts_ms.init_vendorlist_fetches", 0)
diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go
index 72f8fa65..9800ccd7 100755
--- a/exchange/adapter_map.go
+++ b/exchange/adapter_map.go
@@ -25,6 +25,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/adtelligent"
 	"github.com/prebid/prebid-server/adapters/advangelists"
 	"github.com/prebid/prebid-server/adapters/aja"
+	"github.com/prebid/prebid-server/adapters/amx"
 	"github.com/prebid/prebid-server/adapters/applogy"
 	"github.com/prebid/prebid-server/adapters/appnexus"
 	"github.com/prebid/prebid-server/adapters/audienceNetwork"
@@ -63,6 +64,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/mobilefuse"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
 	"github.com/prebid/prebid-server/adapters/ninthdecimal"
+	"github.com/prebid/prebid-server/adapters/nobid"
 	"github.com/prebid/prebid-server/adapters/openx"
 	"github.com/prebid/prebid-server/adapters/orbidder"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
@@ -72,6 +74,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/rtbhouse"
 	"github.com/prebid/prebid-server/adapters/rubicon"
 	"github.com/prebid/prebid-server/adapters/sharethrough"
+	"github.com/prebid/prebid-server/adapters/silvermob"
 	"github.com/prebid/prebid-server/adapters/smaato"
 	"github.com/prebid/prebid-server/adapters/smartadserver"
 	"github.com/prebid/prebid-server/adapters/smartrtb"
@@ -121,6 +124,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderAdtelligent:  adtelligent.NewAdtelligentBidder(cfg.Adapters[string(openrtb_ext.BidderAdtelligent)].Endpoint),
 		openrtb_ext.BidderAdvangelists: advangelists.NewAdvangelistsBidder(cfg.Adapters[string(openrtb_ext.BidderAdvangelists)].Endpoint),
 		openrtb_ext.BidderAJA:          aja.NewAJABidder(cfg.Adapters[string(openrtb_ext.BidderAJA)].Endpoint),
+		openrtb_ext.BidderAMX:          amx.NewAMXBidder(cfg.Adapters[string(openrtb_ext.BidderAMX)].Endpoint),
 		openrtb_ext.BidderApplogy:      applogy.NewApplogyBidder(cfg.Adapters[string(openrtb_ext.BidderApplogy)].Endpoint),
 		openrtb_ext.BidderAppnexus:     appnexus.NewAppNexusBidder(client, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].PlatformID),
 		openrtb_ext.BidderAvocet:       avocet.NewAvocetAdapter(cfg.Adapters[string(openrtb_ext.BidderAvocet)].Endpoint),
@@ -158,6 +162,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderMobileFuse:      mobilefuse.NewMobileFuseBidder(cfg.Adapters[string(openrtb_ext.BidderMobileFuse)].Endpoint),
 		openrtb_ext.BidderNanoInteractive: nanointeractive.NewNanoIneractiveBidder(cfg.Adapters[string(openrtb_ext.BidderNanoInteractive)].Endpoint),
 		openrtb_ext.BidderNinthDecimal:    ninthdecimal.NewNinthDecimalBidder(cfg.Adapters[string(openrtb_ext.BidderNinthDecimal)].Endpoint),
+		openrtb_ext.BidderNoBid:           nobid.NewNoBidBidder(cfg.Adapters[string(openrtb_ext.BidderNoBid)].Endpoint),
 		openrtb_ext.BidderOrbidder:        orbidder.NewOrbidderBidder(cfg.Adapters[string(openrtb_ext.BidderOrbidder)].Endpoint),
 		openrtb_ext.BidderOpenx:           openx.NewOpenxBidder(cfg.Adapters[string(openrtb_ext.BidderOpenx)].Endpoint),
 		openrtb_ext.BidderPubmatic:        pubmatic.NewPubmaticBidder(client, cfg.Adapters[string(openrtb_ext.BidderPubmatic)].Endpoint),
@@ -172,6 +177,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 			cfg.Adapters[string(openrtb_ext.BidderRubicon)].XAPI.Tracker),
 
 		openrtb_ext.BidderSharethrough:     sharethrough.NewSharethroughBidder(cfg.Adapters[string(openrtb_ext.BidderSharethrough)].Endpoint),
+		openrtb_ext.BidderSilverMob:        silvermob.NewSilverMobBidder(cfg.Adapters[string(openrtb_ext.BidderSilverMob)].Endpoint),
 		openrtb_ext.BidderSmaato:           smaato.NewSmaatoBidder(cfg.Adapters[string(openrtb_ext.BidderSmaato)].Endpoint),
 		openrtb_ext.BidderSmartadserver:    smartadserver.NewSmartadserverBidder(cfg.Adapters[string(openrtb_ext.BidderSmartadserver)].Endpoint),
 		openrtb_ext.BidderSmartRTB:         smartrtb.NewSmartRTBBidder(cfg.Adapters[string(openrtb_ext.BidderSmartRTB)].Endpoint),
diff --git a/exchange/bidder.go b/exchange/bidder.go
index 5924e39b..a230041d 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -58,12 +58,14 @@ type adaptedBidder interface {
 // pbsOrtbBid.bidTargets does not need to be filled out by the Bidder. It will be set later by the exchange.
 // pbsOrtbBid.bidVideo is optional but should be filled out by the Bidder if bidType is video.
 // pbsOrtbBid.dealPriority is optionally provided by adapters and used internally by the exchange to support deal targeted campaigns.
+// pbsOrtbBid.dealTierSatisfied is set to true by exchange.updateHbPbCatDur if deal tier satisfied otherwise it will be set to false
 type pbsOrtbBid struct {
-	bid          *openrtb.Bid
-	bidType      openrtb_ext.BidType
-	bidTargets   map[string]string
-	bidVideo     *openrtb_ext.ExtBidPrebidVideo
-	dealPriority int
+	bid               *openrtb.Bid
+	bidType           openrtb_ext.BidType
+	bidTargets        map[string]string
+	bidVideo          *openrtb_ext.ExtBidPrebidVideo
+	dealPriority      int
+	dealTierSatisfied bool
 }
 
 // pbsOrtbSeatBid is a SeatBid returned by an adaptedBidder.
diff --git a/exchange/exchange.go b/exchange/exchange.go
index c1acc0d5..3a5f785b 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -122,7 +122,7 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
 
 	// Slice of BidRequests, each a copy of the original cleaned to only contain bidder data for the named bidder
 	blabels := make(map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels)
-	cleanRequests, aliases, privacyLabels, errs := cleanOpenRTBRequests(ctx, bidRequest, requestExt, usersyncs, blabels, labels, e.gDPR, usersyncIfAmbiguous, e.privacyConfig)
+	cleanRequests, aliases, privacyLabels, errs := cleanOpenRTBRequests(ctx, bidRequest, requestExt, usersyncs, blabels, labels, e.gDPR, usersyncIfAmbiguous, e.privacyConfig, account)
 
 	e.me.RecordRequestPrivacy(privacyLabels)
 
@@ -281,6 +281,7 @@ func validateDealTier(dealTier openrtb_ext.DealTier) bool {
 func updateHbPbCatDur(bid *pbsOrtbBid, dealTier openrtb_ext.DealTier, bidCategory map[string]string) {
 	if bid.dealPriority >= dealTier.MinDealTier {
 		prefixTier := fmt.Sprintf("%s%d_", dealTier.Prefix, bid.dealPriority)
+		bid.dealTierSatisfied = true
 
 		if oldCatDur, ok := bidCategory[bid.bid.ID]; ok {
 			oldCatDurSplit := strings.SplitAfterN(oldCatDur, "_", 2)
@@ -773,9 +774,11 @@ func (e *exchange) makeBid(Bids []*pbsOrtbBid, auc *auction, returnCreative bool
 		bidExt := &openrtb_ext.ExtBid{
 			Bidder: thisBid.bid.Ext,
 			Prebid: &openrtb_ext.ExtBidPrebid{
-				Targeting: thisBid.bidTargets,
-				Type:      thisBid.bidType,
-				Video:     thisBid.bidVideo,
+				Targeting:         thisBid.bidTargets,
+				Type:              thisBid.bidType,
+				Video:             thisBid.bidVideo,
+				DealPriority:      thisBid.dealPriority,
+				DealTierSatisfied: thisBid.dealTierSatisfied,
 			},
 		}
 		if cacheInfo, found := e.getBidCacheInfo(thisBid, auc); found {
diff --git a/exchange/utils.go b/exchange/utils.go
index 63e56e84..f6fcc711 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -19,6 +19,13 @@ import (
 	"github.com/prebid/prebid-server/privacy/lmt"
 )
 
+var integrationTypeMap = map[pbsmetrics.RequestType]config.IntegrationType{
+	pbsmetrics.ReqTypeAMP:      config.IntegrationTypeAMP,
+	pbsmetrics.ReqTypeORTB2App: config.IntegrationTypeApp,
+	pbsmetrics.ReqTypeVideo:    config.IntegrationTypeVideo,
+	pbsmetrics.ReqTypeORTB2Web: config.IntegrationTypeWeb,
+}
+
 const unknownBidder string = ""
 
 func BidderToPrebidSChains(req *openrtb_ext.ExtRequest) (map[string]*openrtb_ext.ExtRequestPrebidSChainSChain, error) {
@@ -53,7 +60,8 @@ func cleanOpenRTBRequests(ctx context.Context,
 	labels pbsmetrics.Labels,
 	gDPR gdpr.Permissions,
 	usersyncIfAmbiguous bool,
-	privacyConfig config.Privacy) (requestsByBidder map[openrtb_ext.BidderName]*openrtb.BidRequest, aliases map[string]string, privacyLabels pbsmetrics.PrivacyLabels, errs []error) {
+	privacyConfig config.Privacy,
+	account *config.Account) (requestsByBidder map[openrtb_ext.BidderName]*openrtb.BidRequest, aliases map[string]string, privacyLabels pbsmetrics.PrivacyLabels, errs []error) {
 
 	impsByBidder, errs := splitImps(orig.Imp)
 	if len(errs) > 0 {
@@ -94,7 +102,9 @@ func cleanOpenRTBRequests(ctx context.Context,
 	privacyLabels.COPPAEnforced = privacyEnforcement.COPPA
 	privacyLabels.LMTEnforced = lmtEnforcer.ShouldEnforce(unknownBidder)
 
-	if gdpr == 1 {
+	gdprEnabled := gdprEnabled(account, privacyConfig, integrationTypeMap[labels.RType])
+
+	if gdpr == 1 && gdprEnabled {
 		privacyLabels.GDPREnforced = true
 		parsedConsent, err := vendorconsent.ParseString(consent)
 		if err == nil {
@@ -109,7 +119,7 @@ func cleanOpenRTBRequests(ctx context.Context,
 		privacyEnforcement.CCPA = ccpaEnforcer.ShouldEnforce(bidder.String())
 
 		// GDPR
-		if gdpr == 1 {
+		if gdpr == 1 && gdprEnabled {
 			coreBidder := resolveBidder(bidder.String(), aliases)
 
 			var publisherID = labels.PubID
@@ -127,6 +137,13 @@ func cleanOpenRTBRequests(ctx context.Context,
 	return
 }
 
+func gdprEnabled(account *config.Account, privacyConfig config.Privacy, integrationType config.IntegrationType) bool {
+	if accountEnabled := account.GDPR.EnabledForIntegrationType(integrationType); accountEnabled != nil {
+		return *accountEnabled
+	}
+	return privacyConfig.GDPR.Enabled
+}
+
 func extractCCPA(orig *openrtb.BidRequest, privacyConfig config.Privacy, aliases map[string]string) (privacy.PolicyEnforcer, error) {
 	ccpaPolicy, err := ccpa.ReadFromRequest(orig)
 	if err != nil {
diff --git a/macros/macros.go b/macros/macros.go
index a9f77ea9..5d6bd7af 100644
--- a/macros/macros.go
+++ b/macros/macros.go
@@ -12,6 +12,7 @@ type EndpointTemplateParams struct {
 	ZoneID      string
 	SourceId    string
 	AccountID   string
+	AdUnit      string
 }
 
 // UserSyncTemplateParams specifies params for an user sync URL template
diff --git a/openrtb_ext/bid.go b/openrtb_ext/bid.go
index 09ee375b..75d83c9d 100644
--- a/openrtb_ext/bid.go
+++ b/openrtb_ext/bid.go
@@ -12,11 +12,15 @@ type ExtBid struct {
 }
 
 // ExtBidPrebid defines the contract for bidresponse.seatbid.bid[i].ext.prebid
+// DealPriority represents priority of deal bid. If its non deal bid then value will be 0
+// DealTierSatisfied true represents corresponding bid has satisfied the deal tier
 type ExtBidPrebid struct {
-	Cache     *ExtBidPrebidCache `json:"cache,omitempty"`
-	Targeting map[string]string  `json:"targeting,omitempty"`
-	Type      BidType            `json:"type"`
-	Video     *ExtBidPrebidVideo `json:"video,omitempty"`
+	Cache             *ExtBidPrebidCache `json:"cache,omitempty"`
+	Targeting         map[string]string  `json:"targeting,omitempty"`
+	Type              BidType            `json:"type"`
+	Video             *ExtBidPrebidVideo `json:"video,omitempty"`
+	DealPriority      int                `json:"dealpriority,omitempty"`
+	DealTierSatisfied bool               `json:"dealtiersatisfied,omitempty"`
 }
 
 // ExtBidPrebidCache defines the contract for  bidresponse.seatbid.bid[i].ext.prebid.cache
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 0493b4da..0fac0800 100755
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -43,6 +43,7 @@ const (
 	BidderAdtelligent      BidderName = "adtelligent"
 	BidderAdvangelists     BidderName = "advangelists"
 	BidderAJA              BidderName = "aja"
+	BidderAMX              BidderName = "amx"
 	BidderApplogy          BidderName = "applogy"
 	BidderAppnexus         BidderName = "appnexus"
 	BidderAdoppler         BidderName = "adoppler"
@@ -82,6 +83,7 @@ const (
 	BidderMobileFuse       BidderName = "mobilefuse"
 	BidderNanoInteractive  BidderName = "nanointeractive"
 	BidderNinthDecimal     BidderName = "ninthdecimal"
+	BidderNoBid            BidderName = "nobid"
 	BidderOpenx            BidderName = "openx"
 	BidderOrbidder         BidderName = "orbidder"
 	BidderPubmatic         BidderName = "pubmatic"
@@ -91,6 +93,7 @@ const (
 	BidderRTBHouse         BidderName = "rtbhouse"
 	BidderRubicon          BidderName = "rubicon"
 	BidderSharethrough     BidderName = "sharethrough"
+	BidderSilverMob        BidderName = "silvermob"
 	BidderSmaato           BidderName = "smaato"
 	BidderSmartadserver    BidderName = "smartadserver"
 	BidderSmartRTB         BidderName = "smartrtb"
@@ -135,6 +138,7 @@ var BidderMap = map[string]BidderName{
 	"adtelligent":       BidderAdtelligent,
 	"advangelists":      BidderAdvangelists,
 	"aja":               BidderAJA,
+	"amx":               BidderAMX,
 	"applogy":           BidderApplogy,
 	"appnexus":          BidderAppnexus,
 	"adoppler":          BidderAdoppler,
@@ -174,6 +178,7 @@ var BidderMap = map[string]BidderName{
 	"mobilefuse":        BidderMobileFuse,
 	"nanointeractive":   BidderNanoInteractive,
 	"ninthdecimal":      BidderNinthDecimal,
+	"nobid":             BidderNoBid,
 	"openx":             BidderOpenx,
 	"orbidder":          BidderOrbidder,
 	"pubmatic":          BidderPubmatic,
@@ -183,6 +188,7 @@ var BidderMap = map[string]BidderName{
 	"rtbhouse":          BidderRTBHouse,
 	"rubicon":           BidderRubicon,
 	"sharethrough":      BidderSharethrough,
+	"silvermob":         BidderSilverMob,
 	"smaato":            BidderSmaato,
 	"smartadserver":     BidderSmartadserver,
 	"smartrtb":          BidderSmartRTB,
diff --git a/openrtb_ext/imp_adoppler.go b/openrtb_ext/imp_adoppler.go
index 4b3ba97c..9d4d5e5c 100644
--- a/openrtb_ext/imp_adoppler.go
+++ b/openrtb_ext/imp_adoppler.go
@@ -1,5 +1,6 @@
 package openrtb_ext
 
 type ExtImpAdoppler struct {
+	Client string `json:"client"`
 	AdUnit string `json:"adunit"`
 }
diff --git a/openrtb_ext/imp_amx.go b/openrtb_ext/imp_amx.go
new file mode 100644
index 00000000..d4439d05
--- /dev/null
+++ b/openrtb_ext/imp_amx.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+// ExtImpAMX is the imp.ext format for the AMX bidder
+type ExtImpAMX struct {
+	TagID    string `json:"tagId,omitempty"`
+	AdUnitID string `json:"adUnitId,omitempty"`
+}
diff --git a/openrtb_ext/imp_nobid.go b/openrtb_ext/imp_nobid.go
new file mode 100644
index 00000000..8af16952
--- /dev/null
+++ b/openrtb_ext/imp_nobid.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ExtImpNoBid struct {
+	SiteID      string `json:"siteId"`
+	PlacementID string `json:"placementId"`
+}
diff --git a/openrtb_ext/imp_silvermob.go b/openrtb_ext/imp_silvermob.go
new file mode 100644
index 00000000..9b246553
--- /dev/null
+++ b/openrtb_ext/imp_silvermob.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+// ExtSilverMob defines the contract for bidrequest.imp[i].ext.silvermob
+type ExtSilverMob struct {
+	ZoneID string `json:"zoneid"`
+	Host   string `json:"host"`
+}
diff --git a/static/bidder-info/33across.yaml b/static/bidder-info/33across.yaml
index 84ba6d68..67e6996a 100644
--- a/static/bidder-info/33across.yaml
+++ b/static/bidder-info/33across.yaml
@@ -4,6 +4,8 @@ capabilities:
   app:
     mediaTypes:
     - banner
+    - video
   site:
     mediaTypes:
     - banner
+    - video
diff --git a/static/bidder-info/amx.yaml b/static/bidder-info/amx.yaml
new file mode 100644
index 00000000..3e20d209
--- /dev/null
+++ b/static/bidder-info/amx.yaml
@@ -0,0 +1,11 @@
+maintainer:
+  email: "prebid@amxrtb.com"
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+  app:
+    mediaTypes:
+      - banner
+      - video
\ No newline at end of file
diff --git a/static/bidder-info/nobid.yaml b/static/bidder-info/nobid.yaml
new file mode 100644
index 00000000..51a55de4
--- /dev/null
+++ b/static/bidder-info/nobid.yaml
@@ -0,0 +1,11 @@
+maintainer:
+  email: "developers@nobid.io"
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+  app:
+    mediaTypes:
+      - banner
+      - video
diff --git a/static/bidder-info/silvermob.yaml b/static/bidder-info/silvermob.yaml
new file mode 100644
index 00000000..5f1e4809
--- /dev/null
+++ b/static/bidder-info/silvermob.yaml
@@ -0,0 +1,8 @@
+maintainer:
+  email: "support@silvermob.com"
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+      - native
\ No newline at end of file
diff --git a/static/bidder-params/adoppler.json b/static/bidder-params/adoppler.json
index c2bdde4f..508eef47 100644
--- a/static/bidder-params/adoppler.json
+++ b/static/bidder-params/adoppler.json
@@ -7,6 +7,10 @@
       "adunit": {
         "type": "string",
         "description": "AdUnit to bid against to."
+      },
+      "client": {
+        "type": "string",
+        "description": "Client name."
       }
   },
   "required": ["adunit"]
diff --git a/static/bidder-params/amx.json b/static/bidder-params/amx.json
new file mode 100644
index 00000000..f9b1b26b
--- /dev/null
+++ b/static/bidder-params/amx.json
@@ -0,0 +1,16 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "AMX RTB Adapter Params",
+  "description": "A schema to validate params accepted by the AMX adapter",
+  "type": "object",
+  "properties": {
+    "tagId" : {
+      "type": "string",
+      "description": "Set a tagId (overrides site.publisher.id, or app.publisher.id)"
+    },
+    "adUnitId": {
+      "type": "string",
+      "description": "Override imp.tagid value to provide a custom value in AMX ad unit ID reporting"
+    }
+  }
+}
diff --git a/static/bidder-params/nobid.json b/static/bidder-params/nobid.json
new file mode 100644
index 00000000..576dbfec
--- /dev/null
+++ b/static/bidder-params/nobid.json
@@ -0,0 +1,18 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "NoBid Adapter Params",
+    "description": "A schema which validates params accepted by the NoBid adapter",
+  
+    "type": "object",
+    "properties": {
+      "siteId": {
+        "type": "integer",
+        "description": "A Required ID which identifies the NoBid site. The siteId paramerter is provided by your NoBid account manager."
+      }, "placementId": { 
+    	  "type": "integer",
+    	  "description": "An oprional ID which identifies an adunit in a site. The placementId paramerter is provided by your NoBid account manager."
+      }
+    },
+    "required": ["siteId"]
+  }
+  
\ No newline at end of file
diff --git a/static/bidder-params/silvermob.json b/static/bidder-params/silvermob.json
new file mode 100644
index 00000000..8ebc85a2
--- /dev/null
+++ b/static/bidder-params/silvermob.json
@@ -0,0 +1,17 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "SilverMob Adapter Params",
+    "description": "A schema which validates params accepted by the SilverMob adapter",
+    "type": "object",
+    "properties": {
+      "zoneid": {
+        "type": "string",
+        "description": "Zone ID"
+      },
+      "host": {
+        "type": "string",
+        "description": "Host"
+      }
+    },
+    "required": ["zoneid", "host"]
+  }
\ No newline at end of file
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
index 4a811aa9..d6b3092a 100755
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -18,6 +18,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/adtelligent"
 	"github.com/prebid/prebid-server/adapters/advangelists"
 	"github.com/prebid/prebid-server/adapters/aja"
+	"github.com/prebid/prebid-server/adapters/amx"
 	"github.com/prebid/prebid-server/adapters/appnexus"
 	"github.com/prebid/prebid-server/adapters/audienceNetwork"
 	"github.com/prebid/prebid-server/adapters/avocet"
@@ -50,6 +51,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/mgid"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
 	"github.com/prebid/prebid-server/adapters/ninthdecimal"
+	"github.com/prebid/prebid-server/adapters/nobid"
 	"github.com/prebid/prebid-server/adapters/openx"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
 	"github.com/prebid/prebid-server/adapters/pulsepoint"
@@ -101,6 +103,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdtelligent, adtelligent.NewAdtelligentSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdvangelists, advangelists.NewAdvangelistsSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAJA, aja.NewAJASyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderAMX, amx.NewAMXSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAppnexus, appnexus.NewAppnexusSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAvocet, avocet.NewAvocetSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBeachfront, beachfront.NewBeachfrontSyncer)
@@ -133,6 +136,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMgid, mgid.NewMgidSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderNanoInteractive, nanointeractive.NewNanoInteractiveSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderNinthDecimal, ninthdecimal.NewNinthDecimalSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderNoBid, nobid.NewNoBidSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderOpenx, openx.NewOpenxSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderPubmatic, pubmatic.NewPubmaticSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderPulsepoint, pulsepoint.NewPulsepointSyncer)


Test patch:
diff --git a/adapters/33across/33across_test.go b/adapters/33across/33across_test.go
index ccdcbf9c..9856f8f9 100644
--- a/adapters/33across/33across_test.go
+++ b/adapters/33across/33across_test.go
@@ -7,5 +7,5 @@ import (
 )
 
 func TestJsonSamples(t *testing.T) {
-	adapterstest.RunJSONBidderTest(t, "33across", New33AcrossBidder("http://ssc.33across.com"))
+	adapterstest.RunJSONBidderTest(t, "33acrosstest", New33AcrossBidder("http://ssc.33across.com"))
 }
diff --git a/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json b/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json
new file mode 100644
index 00000000..bb0e6585
--- /dev/null
+++ b/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json
@@ -0,0 +1,100 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "w": 728, 
+          "h": 90,
+          "protocols": [2],
+          "placement": 1,
+          "startdelay": -2,
+          "playbackmethod": [2],
+          "mimes": ["foo", "bar"]
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-site-id",
+            "productId": "instream"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://ssc.33across.com",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "video": {
+                "w": 728, 
+                "h": 90,
+                "protocols": [2],
+                "placement": 1,
+                "startdelay": -2,
+                "playbackmethod": [2],
+                "mimes": ["foo", "bar"]
+              },
+              "ext": {
+                "ttx": {
+                  "prod": "instream"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "fake-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-vast-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-vast-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json b/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json
new file mode 100644
index 00000000..479b1970
--- /dev/null
+++ b/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json
@@ -0,0 +1,108 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "w": 728, 
+          "h": 90,
+          "protocols": [2],
+          "playbackmethod": [2],
+          "mimes": ["foo", "bar"]
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-site-id",
+            "productId": "instream"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://ssc.33across.com",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "video": {
+                "w": 728, 
+                "h": 90,
+                "protocols": [2],
+                "placement": 1,
+                "startdelay": 0,
+                "playbackmethod": [2],
+                "mimes": ["foo", "bar"]
+              },
+              "ext": {
+                "ttx": {
+                  "prod": "instream"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "fake-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-vast-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728,
+                "ext": {
+                  "ttx": {
+                    "mediaType": "video"
+                  }
+                }
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-vast-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90,
+            "ext": {
+              "ttx": {
+                "mediaType": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/33across/33acrosstest/exemplary/multi-format.json b/adapters/33across/33acrosstest/exemplary/multi-format.json
new file mode 100644
index 00000000..db15955c
--- /dev/null
+++ b/adapters/33across/33acrosstest/exemplary/multi-format.json
@@ -0,0 +1,103 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "video": {
+          "w": 728, 
+          "h": 90,
+          "protocols": [2],
+          "playbackmethod": [2],
+          "mimes": ["foo", "bar"]
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-site-id",
+            "productId": "inview"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://ssc.33across.com",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}]
+              },
+              "video": {
+                "w": 728, 
+                "h": 90,
+                "protocols": [2],
+                "placement": 2,
+                "playbackmethod": [2],
+                "mimes": ["foo", "bar"]
+              },
+              "ext": {
+                "ttx": {
+                  "prod": "inview"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "fake-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/33across/33across/exemplary/optional-params.json b/adapters/33across/33acrosstest/exemplary/optional-params.json
similarity index 100%
rename from adapters/33across/33across/exemplary/optional-params.json
rename to adapters/33across/33acrosstest/exemplary/optional-params.json
diff --git a/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json b/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json
new file mode 100644
index 00000000..c0c31168
--- /dev/null
+++ b/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json
@@ -0,0 +1,107 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "w": 728, 
+          "h": 90,
+          "protocols": [2],
+          "playbackmethod": [2],
+          "mimes": ["foo", "bar"]
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-site-id",
+            "productId": "siab"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://ssc.33across.com",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "video": {
+                "w": 728, 
+                "h": 90,
+                "protocols": [2],
+                "placement": 2,
+                "playbackmethod": [2],
+                "mimes": ["foo", "bar"]
+              },
+              "ext": {
+                "ttx": {
+                  "prod": "siab"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "fake-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-vast-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728,
+                "ext": {
+                  "ttx": {
+                    "mediaType": "video"
+                  }
+                }
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-vast-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90,
+            "ext": {
+              "ttx": {
+                "mediaType": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/33across/33acrosstest/exemplary/simple-video.json b/adapters/33across/33acrosstest/exemplary/simple-video.json
new file mode 100644
index 00000000..55337b92
--- /dev/null
+++ b/adapters/33across/33acrosstest/exemplary/simple-video.json
@@ -0,0 +1,110 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "w": 728, 
+          "h": 90,
+          "protocols": [2],
+          "placement": 1,
+          "startdelay": -2,
+          "playbackmethod": [2],
+          "mimes": ["foo", "bar"]
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-site-id",
+            "productId": "instream"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://ssc.33across.com",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "video": {
+                "w": 728, 
+                "h": 90,
+                "protocols": [2],
+                "placement": 1,
+                "startdelay": -2,
+                "playbackmethod": [2],
+                "mimes": ["foo", "bar"]
+              },
+              "ext": {
+                "ttx": {
+                  "prod": "instream"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "fake-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "ttx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-vast-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728,
+                "ext": {
+                  "ttx": {
+                    "mediaType": "video"
+                  }
+                }
+              }]
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-vast-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90,
+            "ext": {
+              "ttx": {
+                "mediaType": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/33across/33across/params/race/banner.json b/adapters/33across/33acrosstest/params/race/banner.json
similarity index 100%
rename from adapters/33across/33across/params/race/banner.json
rename to adapters/33across/33acrosstest/params/race/banner.json
diff --git a/adapters/33across/33acrosstest/params/race/video.json b/adapters/33across/33acrosstest/params/race/video.json
new file mode 100644
index 00000000..9df849ad
--- /dev/null
+++ b/adapters/33across/33acrosstest/params/race/video.json
@@ -0,0 +1,6 @@
+{
+    "productId": "siab",
+    "siteId": "33across",
+    "zoneId": "33AcrossZone"
+  }
+  
\ No newline at end of file
diff --git a/adapters/33across/33acrosstest/supplemental/status-not-ok.json b/adapters/33across/33acrosstest/supplemental/status-not-ok.json
new file mode 100644
index 00000000..98fe01c2
--- /dev/null
+++ b/adapters/33across/33acrosstest/supplemental/status-not-ok.json
@@ -0,0 +1,67 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-invalid-site-id",
+            "productId": "inview"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://ssc.33across.com",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id":"test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}]
+              },
+              "ext": {
+                "ttx": {
+                  "prod": "inview"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "fake-invalid-site-id"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 400,
+        "body": {
+          "error": {
+            "message": "Validation failed",
+            "details": [
+              {
+                "message": "site.id is invalid"
+              }
+            ]
+        }
+        }
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/33across/33acrosstest/supplemental/video-validation-fail.json b/adapters/33across/33acrosstest/supplemental/video-validation-fail.json
new file mode 100644
index 00000000..97cb79bd
--- /dev/null
+++ b/adapters/33across/33acrosstest/supplemental/video-validation-fail.json
@@ -0,0 +1,32 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "w": 728, 
+          "h": 90
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "fake-site-id",
+            "productId": "siab"
+          }
+        }
+      }
+    ],
+    "site": {}
+  },
+  
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "One or more invalid or missing video field(s) w, h, protocols, mimes, playbackmethod",
+      "comparison": "literal"
+    },
+    {
+      "value": "At least one of [banner, video] formats must be defined in Imp. None found",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adhese/adhesetest/exemplary/banner-internal.json b/adapters/adhese/adhesetest/exemplary/banner-internal.json
index 3a31d0cc..50efe4a6 100644
--- a/adapters/adhese/adhesetest/exemplary/banner-internal.json
+++ b/adapters/adhese/adhesetest/exemplary/banner-internal.json
@@ -37,12 +37,15 @@
       "publisher": {
         "id": "123"
       }
+    },
+    "device": {
+      "IFA": "dum-my"
     }
   },
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy"
+        "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy/xzdum-my"
       },
       "mockResponse": {
         "status": 200,
diff --git a/adapters/adoppler/adoppler_test.go b/adapters/adoppler/adoppler_test.go
index e7d908df..646852a1 100644
--- a/adapters/adoppler/adoppler_test.go
+++ b/adapters/adoppler/adoppler_test.go
@@ -7,6 +7,6 @@ import (
 )
 
 func TestJsonSamples(t *testing.T) {
-	bidder := NewAdopplerBidder("http://adoppler.com")
+	bidder := NewAdopplerBidder("http://{{.AccountID}}.trustedmarketplace.com/processHeaderBid/{{.AdUnit}}")
 	adapterstest.RunJSONBidderTest(t, "adopplertest", bidder)
 }
diff --git a/adapters/adoppler/adopplertest/exemplary/custom-client.json b/adapters/adoppler/adopplertest/exemplary/custom-client.json
new file mode 100644
index 00000000..6bb32f71
--- /dev/null
+++ b/adapters/adoppler/adopplertest/exemplary/custom-client.json
@@ -0,0 +1,80 @@
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1",
+            "client":"client1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://client1.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1",
+                  "client":"client1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-unit1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-unit1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>An ad</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+    {
+      "currency":"USD",
+      "bids":[
+        {
+          "bid":{
+            "id":"req1-unit1-bid1",
+            "impid":"imp1",
+            "price":0.12,
+            "adm":"<b>An ad</b>"
+          },
+          "type":"banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/exemplary/default-client.json b/adapters/adoppler/adopplertest/exemplary/default-client.json
new file mode 100644
index 00000000..25fb7197
--- /dev/null
+++ b/adapters/adoppler/adopplertest/exemplary/default-client.json
@@ -0,0 +1,78 @@
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-unit1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-unit1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>An ad</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+    {
+      "currency":"USD",
+      "bids":[
+        {
+          "bid":{
+            "id":"req1-unit1-bid1",
+            "impid":"imp1",
+            "price":0.12,
+            "adm":"<b>An ad</b>"
+          },
+          "type":"banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/exemplary/multibid.json b/adapters/adoppler/adopplertest/exemplary/multibid.json
deleted file mode 100644
index 851f4c5b..00000000
--- a/adapters/adoppler/adopplertest/exemplary/multibid.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}},
-                           {"id": "imp2",
-                            "video": {"minduration": 120,
-                                      "mimes": ["video/mp4"]},
-                            "ext": {"bidder": {"adunit": "unit2"}}},
-                           {"id": "imp3",
-                            "native": {"request": "{}"},
-                            "ext": {"bidder": {"adunit": "unit3"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit2",
-                                    "body": {"id": "req1-unit2",
-                                        "imp": [{"id": "imp2",
-                                                 "video": {"minduration": 120,
-                                                           "mimes": ["video/mp4"]},
-                                                 "ext": {"bidder": {"adunit": "unit2"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp2-resp2",
-                                          "seatbid": [{"bid": [{"id": "req1-imp2-bid1",
-                                                                "impid": "imp2",
-                                                                "price": 0.24,
-                                                                "adm": "<VAST />",
-                                                                "cat": ["IAB1", "IAB2"],
-                                                                "ext": {"ads": {"video": {"duration": 121}}}}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit3",
-                                    "body": {"id": "req1-unit3",
-                                        "imp": [{"id": "imp3",
-                                                 "native": {"request": "{}"},
-                                                 "ext": {"bidder": {"adunit": "unit3"}}}]}},
-                "mockResponse": {"status": 204,
-                                 "body": ""}}],
- "expectedBidResponses": [{"currency": "USD",
-                           "bids": [{"bid": {"id": "req1-imp1-bid1",
-                                             "impid": "imp1",
-                                             "price": 0.12,
-                                             "adm": "<b>a banner</b>"},
-                                     "type": "banner"}]},
-                          {"currency": "USD",
-                           "bids": [{"bid": {"id": "req1-imp2-bid1",
-                                             "impid": "imp2",
-                                             "price": 0.24,
-                                             "adm": "<VAST />",
-                                             "cat": ["IAB1", "IAB2"],
-                                             "ext": {"ads": {"video": {"duration": 121}}}},
-                                     "type": "video"}]}]}
diff --git a/adapters/adoppler/adopplertest/exemplary/multiimp.json b/adapters/adoppler/adopplertest/exemplary/multiimp.json
new file mode 100644
index 00000000..6eebbe43
--- /dev/null
+++ b/adapters/adoppler/adopplertest/exemplary/multiimp.json
@@ -0,0 +1,207 @@
+{
+   "mockBidRequest":{
+      "id":"req1",
+      "imp":[
+         {
+            "id":"imp1",
+            "banner":{
+               "w":100,
+               "h":200
+            },
+            "ext":{
+               "bidder":{
+                  "adunit":"unit1"
+               }
+            }
+         },
+         {
+            "id":"imp2",
+            "video":{
+               "minduration":120,
+               "mimes":[
+                  "video/mp4"
+               ]
+            },
+            "ext":{
+               "bidder":{
+                  "adunit":"unit2"
+               }
+            }
+         },
+         {
+            "id":"imp3",
+            "native":{
+               "request":"{}"
+            },
+            "ext":{
+               "bidder":{
+                  "adunit":"unit3"
+               }
+            }
+         }
+      ]
+   },
+   "httpCalls":[
+      {
+         "expectedRequest":{
+            "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+            "body":{
+               "id":"req1-unit1",
+               "imp":[
+                  {
+                     "id":"imp1",
+                     "banner":{
+                        "w":100,
+                        "h":200
+                     },
+                     "ext":{
+                        "bidder":{
+                           "adunit":"unit1"
+                        }
+                     }
+                  }
+               ]
+            }
+         },
+         "mockResponse":{
+            "status":200,
+            "body":{
+               "id":"req1-imp1-resp1",
+               "seatbid":[
+                  {
+                     "bid":[
+                        {
+                           "id":"req1-imp1-bid1",
+                           "impid":"imp1",
+                           "price":0.12,
+                           "adm":"<b>a banner</b>"
+                        }
+                     ]
+                  }
+               ],
+               "cur":"USD"
+            }
+         }
+      },
+      {
+         "expectedRequest":{
+            "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit2",
+            "body":{
+               "id":"req1-unit2",
+               "imp":[
+                  {
+                     "id":"imp2",
+                     "video":{
+                        "minduration":120,
+                        "mimes":[
+                           "video/mp4"
+                        ]
+                     },
+                     "ext":{
+                        "bidder":{
+                           "adunit":"unit2"
+                        }
+                     }
+                  }
+               ]
+            }
+         },
+         "mockResponse":{
+            "status":200,
+            "body":{
+               "id":"req1-imp2-resp2",
+               "seatbid":[
+                  {
+                     "bid":[
+                        {
+                           "id":"req1-imp2-bid1",
+                           "impid":"imp2",
+                           "price":0.24,
+                           "adm":"<VAST />",
+                           "cat":[
+                              "IAB1",
+                              "IAB2"
+                           ],
+                           "ext":{
+                              "ads":{
+                                 "video":{
+                                    "duration":121
+                                 }
+                              }
+                           }
+                        }
+                     ]
+                  }
+               ],
+               "cur":"USD"
+            }
+         }
+      },
+      {
+         "expectedRequest":{
+            "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit3",
+            "body":{
+               "id":"req1-unit3",
+               "imp":[
+                  {
+                     "id":"imp3",
+                     "native":{
+                        "request":"{}"
+                     },
+                     "ext":{
+                        "bidder":{
+                           "adunit":"unit3"
+                        }
+                     }
+                  }
+               ]
+            }
+         },
+         "mockResponse":{
+            "status":204,
+            "body":""
+         }
+      }
+   ],
+   "expectedBidResponses":[
+      {
+         "currency":"USD",
+         "bids":[
+            {
+               "bid":{
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+               },
+               "type":"banner"
+            }
+         ]
+      },
+      {
+         "currency":"USD",
+         "bids":[
+            {
+               "bid":{
+                  "id":"req1-imp2-bid1",
+                  "impid":"imp2",
+                  "price":0.24,
+                  "adm":"<VAST />",
+                  "cat":[
+                     "IAB1",
+                     "IAB2"
+                  ],
+                  "ext":{
+                     "ads":{
+                        "video":{
+                           "duration":121
+                        }
+                     }
+                  }
+               },
+               "type":"video"
+            }
+         ]
+      }
+   ]
+}
diff --git a/adapters/adoppler/adopplertest/exemplary/no-bid.json b/adapters/adoppler/adopplertest/exemplary/no-bid.json
deleted file mode 100644
index 0e0f1358..00000000
--- a/adapters/adoppler/adopplertest/exemplary/no-bid.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 204,
-                                 "body": ""}}],
- "expectedBidResponses": []}
diff --git a/adapters/adoppler/adopplertest/supplemental/bad-request.json b/adapters/adoppler/adopplertest/supplemental/bad-request.json
index 3bdd5a55..ae515e01 100644
--- a/adapters/adoppler/adopplertest/supplemental/bad-request.json
+++ b/adapters/adoppler/adopplertest/supplemental/bad-request.json
@@ -1,15 +1,56 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 400,
-                                 "body": ""}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "bad request",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":400,
+        "body":""
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"bad request",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json b/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json
index 4382e36c..d6f17a6b 100644
--- a/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json
+++ b/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json
@@ -1,38 +1,128 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}},
-                           {"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit2"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit2",
-                                    "body": {"id": "req1-unit2",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit2"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "duplicate $.imp.id imp1",
-                             "comparison": "literal"},
-                            {"value": "duplicate $.imp.id imp1",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      },
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit2"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    },
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit2",
+        "body":{
+          "id":"req1-unit2",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit2"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"duplicate $.imp.id imp1",
+      "comparison":"literal"
+    },
+    {
+      "value":"duplicate $.imp.id imp1",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/invalid-impid.json b/adapters/adoppler/adopplertest/supplemental/invalid-impid.json
index 2e6ecf4a..b5f062ac 100644
--- a/adapters/adoppler/adopplertest/supplemental/invalid-impid.json
+++ b/adapters/adoppler/adopplertest/supplemental/invalid-impid.json
@@ -1,20 +1,71 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "invalid",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "unknown impid: invalid",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"invalid",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"unknown impid: invalid",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/invalid-response.json b/adapters/adoppler/adopplertest/supplemental/invalid-response.json
index 72420881..d0a7d2ef 100644
--- a/adapters/adoppler/adopplertest/supplemental/invalid-response.json
+++ b/adapters/adoppler/adopplertest/supplemental/invalid-response.json
@@ -1,15 +1,56 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": "invalid-json"}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "invalid body: json: cannot unmarshal string into Go value of type openrtb.BidResponse",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":"invalid-json"
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"invalid body: json: cannot unmarshal string into Go value of type openrtb.BidResponse",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json b/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json
index d9cb6daa..c08cdca5 100644
--- a/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json
+++ b/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json
@@ -1,43 +1,145 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "video": {"minduration": 120,
-                                      "mimes": ["video/mp4"]},
-                            "ext": {"bidder": {"adunit": "unit1"}}},
-                          {"id": "imp2",
-                           "video": {"minduration": 120,
-                                     "mimes": ["video/mp4"]},
-                           "ext": {"bidder": {"adunit": "unit2"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "video": {"minduration": 120,
-                                                           "mimes": ["video/mp4"]},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.24,
-                                                                "adm": "<VAST />",
-                                                                "cat": ["IAB1", "IAB2"],
-                                                                "ext": {}}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit2",
-                                    "body": {"id": "req1-unit2",
-                                        "imp": [{"id": "imp2",
-                                                 "video": {"minduration": 120,
-                                                           "mimes": ["video/mp4"]},
-                                                 "ext": {"bidder": {"adunit": "unit2"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp2-resp2",
-                                          "seatbid": [{"bid": [{"id": "req1-imp2-bid2",
-                                                                "impid": "imp2",
-                                                                "price": 0.24,
-                                                                "adm": "<VAST />",
-                                                                "cat": ["IAB1", "IAB2"],
-                                                                "ext": ""}]}],
-                                          "cur": "USD"}}}],
- "expectedMakeBidsErrors": [{"value": "$.seatbid.bid.ext.ads.video required",
-                             "comparison": "literal"},
-                            {"value": "json: cannot unmarshal string into Go value of type struct { Ads *adoppler.adsImpExt \"json:\\\"ads\\\"\" }",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "video":{
+          "minduration":120,
+          "mimes":[
+            "video/mp4"
+          ]
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      },
+      {
+        "id":"imp2",
+        "video":{
+          "minduration":120,
+          "mimes":[
+            "video/mp4"
+          ]
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit2"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "video":{
+                "minduration":120,
+                "mimes":[
+                  "video/mp4"
+                ]
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.24,
+                  "adm":"<VAST />",
+                  "cat":[
+                    "IAB1",
+                    "IAB2"
+                  ],
+                  "ext":{
+
+                  }
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    },
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit2",
+        "body":{
+          "id":"req1-unit2",
+          "imp":[
+            {
+              "id":"imp2",
+              "video":{
+                "minduration":120,
+                "mimes":[
+                  "video/mp4"
+                ]
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit2"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp2-resp2",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp2-bid2",
+                  "impid":"imp2",
+                  "price":0.24,
+                  "adm":"<VAST />",
+                  "cat":[
+                    "IAB1",
+                    "IAB2"
+                  ],
+                  "ext":""
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"$.seatbid.bid.ext.ads.video required",
+      "comparison":"literal"
+    },
+    {
+      "value":"json: cannot unmarshal string into Go value of type struct { Ads *adoppler.adsImpExt \"json:\\\"ads\\\"\" }",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/missing-adunit.json b/adapters/adoppler/adopplertest/supplemental/missing-adunit.json
index 82a6a95e..df9bbe57 100644
--- a/adapters/adoppler/adopplertest/supplemental/missing-adunit.json
+++ b/adapters/adoppler/adopplertest/supplemental/missing-adunit.json
@@ -1,9 +1,31 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {}}}]},
- "httpCalls": [],
- "expectedBidResponses": [],
- "expectedMakeRequestsErrors": [{"value": "$.imp.ext.adoppler.adunit required",
-                                 "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeRequestsErrors":[
+    {
+      "value":"$.imp.ext.adoppler.adunit required",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/no-bid.json b/adapters/adoppler/adopplertest/supplemental/no-bid.json
new file mode 100644
index 00000000..08a29481
--- /dev/null
+++ b/adapters/adoppler/adopplertest/supplemental/no-bid.json
@@ -0,0 +1,50 @@
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":204,
+        "body":""
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/server-error.json b/adapters/adoppler/adopplertest/supplemental/server-error.json
index df23bac0..604b83e7 100644
--- a/adapters/adoppler/adopplertest/supplemental/server-error.json
+++ b/adapters/adoppler/adopplertest/supplemental/server-error.json
@@ -1,15 +1,56 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 500,
-                                 "body": ""}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "unexpected status: 500",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":500,
+        "body":""
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"unexpected status: 500",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adtelligent/usersync_test.go b/adapters/adtelligent/usersync_test.go
index 1cc5dfe4..fa157d22 100644
--- a/adapters/adtelligent/usersync_test.go
+++ b/adapters/adtelligent/usersync_test.go
@@ -25,6 +25,6 @@ func TestAdtelligentSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//sync.adtelligent.com/csync?t=p&ep=0&redir=localhost%2Fsetuid%3Fbidder%3Dadtelligent%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%7Buid%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
+	assert.EqualValues(t, 410, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/amx/amx_test.go b/adapters/amx/amx_test.go
new file mode 100644
index 00000000..292e65c2
--- /dev/null
+++ b/adapters/amx/amx_test.go
@@ -0,0 +1,180 @@
+package amx
+
+import (
+	"encoding/json"
+	"fmt"
+	"regexp"
+	"testing"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+const (
+	amxTestEndpoint  = "http://pbs-dev.amxrtb.com/auction/openrtb"
+	sampleVastADM    = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><VAST version=\"2.0\"><Ad id=\"128a6.44d74.46b3\"><InLine><Error><![CDATA[http://example.net/hbx/verr?e=]]></Error><Impression><![CDATA[http://example.net/hbx/vimp?lid=test&aid=testapp]]></Impression><Creatives><Creative sequence=\"1\"><Linear><Duration>00:00:15</Duration><TrackingEvents><Tracking event=\"firstQuartile\"><![CDATA[https://example.com?event=first_quartile]]></Tracking></TrackingEvents><VideoClicks><ClickThrough><![CDATA[http://example.com]]></ClickThrough></VideoClicks><MediaFiles><MediaFile delivery=\"progressive\" width=\"16\" height=\"9\" type=\"video/mp4\" bitrate=\"800\"><![CDATA[https://example.com/media.mp4]]></MediaFile></MediaFiles></Linear></Creative></Creatives></InLine></Ad></VAST>"
+	sampleDisplayADM = "<img src='https://example.com/300x250.png' height='250' width='300'/>"
+)
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "amxtest", NewAMXBidder(amxTestEndpoint))
+}
+
+func TestMakeRequestsTagID(t *testing.T) {
+	var w, h int = 300, 250
+	var width, height uint64 = uint64(w), uint64(h)
+	adapter := NewAMXBidder(amxTestEndpoint)
+
+	type testCase struct {
+		tagID         string
+		extAdUnitID   string
+		expectedTagID string
+		blankNil      bool
+	}
+
+	tests := []testCase{
+		{tagID: "tag-id", extAdUnitID: "ext.adUnitID", expectedTagID: "ext.adUnitID", blankNil: false},
+		{tagID: "tag-id", extAdUnitID: "", expectedTagID: "tag-id", blankNil: false},
+		{tagID: "tag-id", extAdUnitID: "", expectedTagID: "tag-id", blankNil: true},
+		{tagID: "", extAdUnitID: "", expectedTagID: "", blankNil: true},
+		{tagID: "", extAdUnitID: "", expectedTagID: "", blankNil: false},
+		{tagID: "", extAdUnitID: "ext.adUnitID", expectedTagID: "ext.adUnitID", blankNil: true},
+		{tagID: "", extAdUnitID: "ext.adUnitID", expectedTagID: "ext.adUnitID", blankNil: false},
+	}
+
+	for _, tc := range tests {
+		imp1 := openrtb.Imp{
+			ID: "sample_imp_1",
+			Banner: &openrtb.Banner{
+				W: &width,
+				H: &height,
+				Format: []openrtb.Format{
+					{W: 300, H: 250},
+				},
+			}}
+
+		if tc.extAdUnitID != "" || !tc.blankNil {
+			imp1.Ext = json.RawMessage(
+				fmt.Sprintf(`{"bidder":{"adUnitId":"%s"}}`, tc.extAdUnitID))
+		}
+
+		if tc.tagID != "" || !tc.blankNil {
+			imp1.TagID = tc.tagID
+		}
+
+		inputRequest := openrtb.BidRequest{
+			User: &openrtb.User{},
+			Imp:  []openrtb.Imp{imp1},
+			Site: &openrtb.Site{},
+		}
+
+		actualAdapterRequests, err := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+		assert.Len(t, actualAdapterRequests, 1)
+		assert.Empty(t, err)
+		var body openrtb.BidRequest
+		assert.Nil(t, json.Unmarshal(actualAdapterRequests[0].Body, &body))
+		assert.Equal(t, tc.expectedTagID, body.Imp[0].TagID)
+	}
+}
+
+func TestMakeRequestsPublisherId(t *testing.T) {
+	var w, h int = 300, 250
+	var width, height uint64 = uint64(w), uint64(h)
+	adapter := NewAMXBidder(amxTestEndpoint)
+
+	type testCase struct {
+		publisherID         string
+		extTagID            string
+		expectedPublisherID string
+		blankNil            bool
+	}
+
+	tests := []testCase{
+		{publisherID: "publisher.id", extTagID: "ext.tagId", expectedPublisherID: "ext.tagId", blankNil: false},
+		{publisherID: "publisher.id", extTagID: "", expectedPublisherID: "publisher.id", blankNil: false},
+		{publisherID: "", extTagID: "ext.tagId", expectedPublisherID: "ext.tagId", blankNil: false},
+		{publisherID: "", extTagID: "ext.tagId", expectedPublisherID: "ext.tagId", blankNil: true},
+		{publisherID: "publisher.id", extTagID: "", expectedPublisherID: "publisher.id", blankNil: false},
+		{publisherID: "publisher.id", extTagID: "", expectedPublisherID: "publisher.id", blankNil: true},
+	}
+
+	for _, tc := range tests {
+		imp1 := openrtb.Imp{
+			ID: "sample_imp_1",
+			Banner: &openrtb.Banner{
+				W: &width,
+				H: &height,
+				Format: []openrtb.Format{
+					{W: 300, H: 250},
+				},
+			}}
+
+		if tc.extTagID != "" || !tc.blankNil {
+			imp1.Ext = json.RawMessage(
+				fmt.Sprintf(`{"bidder":{"tagId":"%s"}}`, tc.extTagID))
+		}
+
+		inputRequest := openrtb.BidRequest{
+			User: &openrtb.User{ID: "example_user_id"},
+			Imp:  []openrtb.Imp{imp1},
+			Site: &openrtb.Site{},
+			ID:   "1234",
+		}
+
+		if tc.publisherID != "" || !tc.blankNil {
+			inputRequest.Site.Publisher = &openrtb.Publisher{
+				ID: tc.publisherID,
+			}
+		}
+
+		actualAdapterRequests, err := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+		assert.Len(t, actualAdapterRequests, 1)
+		assert.Empty(t, err)
+		var body openrtb.BidRequest
+		assert.Nil(t, json.Unmarshal(actualAdapterRequests[0].Body, &body))
+		assert.Equal(t, tc.expectedPublisherID, body.Site.Publisher.ID)
+	}
+}
+
+var vastImpressionRXP = regexp.MustCompile(`<Impression><!\[CDATA\[[^\]]*\]\]></Impression>`)
+
+func countImpressionPixels(vast string) int {
+	matches := vastImpressionRXP.FindAllIndex([]byte(vast), -1)
+	return len(matches)
+}
+
+func TestVideoImpInsertion(t *testing.T) {
+	markup := interpolateImpressions(openrtb.Bid{
+		AdM:  sampleVastADM,
+		NURL: "https://example2.com/nurl",
+	}, amxBidExt{Himp: []string{"https://example.com/pixel.png"}})
+	assert.Contains(t, markup, "example2.com/nurl")
+	assert.Contains(t, markup, "example.com/pixel.png")
+	assert.Equal(t, 3, countImpressionPixels(markup), "should have 3 Impression pixels")
+
+	// make sure that a blank NURL won't result in a blank impression tag
+	markup = interpolateImpressions(openrtb.Bid{
+		AdM:  sampleVastADM,
+		NURL: "",
+	}, amxBidExt{})
+	assert.Equal(t, 1, countImpressionPixels(markup), "should have 1 impression pixels")
+
+	// we should also ignore blank ext.Himp pixels
+	markup = interpolateImpressions(openrtb.Bid{
+		AdM:  sampleVastADM,
+		NURL: "https://example-nurl.com/nurl",
+	}, amxBidExt{Himp: []string{"", "", ""}})
+	assert.Equal(t, 2, countImpressionPixels(markup), "should have 2 impression pixels")
+}
+
+func TestNoDisplayImpInsertion(t *testing.T) {
+	data := interpolateImpressions(openrtb.Bid{
+		AdM:  sampleDisplayADM,
+		NURL: "https://example2.com/nurl",
+	}, amxBidExt{Himp: []string{"https://example.com/pixel.png"}})
+	assert.NotContains(t, data, "example2.com/nurl")
+	assert.NotContains(t, data, "example.com/pixel.png")
+}
diff --git a/adapters/amx/amxtest/exemplary/app-simple.json b/adapters/amx/amxtest/exemplary/app-simple.json
new file mode 100644
index 00000000..b2f53849
--- /dev/null
+++ b/adapters/amx/amxtest/exemplary/app-simple.json
@@ -0,0 +1,178 @@
+{
+  "mockBidRequest": {
+    "allimps": 0,
+    "app": {
+      "bundle": "639881495",
+      "name": "Imgur (iOS)",
+      "storeurl": "https://apps.apple.com/us/app/imgur-meme-gif-maker/id639881495",
+      "ver": "2020.4",
+      "publisher": {
+        "id": "unused-overridden"
+      }
+    },
+    "device": {
+      "connectiontype": 2,
+      "dnt": 0,
+      "h": 1024,
+      "ifa": "201461F8-0F14-4ADD-A87F-AAAAAAAAA",
+      "ip": "73.221.0.0",
+      "language": "en",
+      "os": "ios",
+      "ua": "Mozilla/5.0 (iPad; CPU OS 12_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
+      "w": 768
+    },
+    "id": "WQ5V2DWVTMNXRSWL",
+    "imp": [
+      {
+        "banner": {
+          "api": [
+            3,
+            5
+          ],
+          "format": [
+            {
+              "h": 50,
+              "w": 320
+            }
+          ],
+          "h": 50,
+          "pos": 1,
+          "topframe": 1,
+          "w": 320
+        },
+        "bidfloor": 0.5,
+        "bidfloorcur": "USD",
+        "clickbrowser": 1,
+        "id": "1",
+        "instl": 1,
+        "secure": 1,
+        "ext": {
+          "bidder": {
+            "tagId": "cHJlYmlkLm9yZw",
+            "adUnitId": "sample-ad-unit-id"
+          }
+        }
+      }
+    ],
+    "regs": {
+      "ext": {
+        "gdpr": 0
+      }
+    },
+    "tmax": 300
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://pbs-dev.amxrtb.com/auction/openrtb?v=pbs1.0",
+        "body": {
+          "app": {
+            "bundle": "639881495",
+            "name": "Imgur (iOS)",
+            "storeurl": "https://apps.apple.com/us/app/imgur-meme-gif-maker/id639881495",
+            "ver": "2020.4",
+            "publisher": {
+              "id": "cHJlYmlkLm9yZw"
+            }
+          },
+          "device": {
+            "connectiontype": 2,
+            "dnt": 0,
+            "h": 1024,
+            "ifa": "201461F8-0F14-4ADD-A87F-AAAAAAAAA",
+            "ip": "73.221.0.0",
+            "language": "en",
+            "os": "ios",
+            "ua": "Mozilla/5.0 (iPad; CPU OS 12_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
+            "w": 768
+          },
+          "id": "WQ5V2DWVTMNXRSWL",
+          "imp": [
+            {
+              "banner": {
+                "api": [
+                  3,
+                  5
+                ],
+                "format": [
+                  {
+                    "h": 50,
+                    "w": 320
+                  }
+                ],
+                "h": 50,
+                "pos": 1,
+                "topframe": 1,
+                "w": 320
+              },
+              "bidfloor": 0.5,
+              "bidfloorcur": "USD",
+              "clickbrowser": 1,
+              "id": "1",
+              "instl": 1,
+              "secure": 1,
+              "tagid": "sample-ad-unit-id",
+              "ext": {
+                "bidder": {
+                  "tagId": "cHJlYmlkLm9yZw",
+                  "adUnitId": "sample-ad-unit-id"
+                }
+              }
+            }
+          ],
+          "regs": {
+            "ext": {
+              "gdpr": 0
+            }
+          },
+          "tmax": 300
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "WQ5V2DWVTMNXRSWL",
+          "seatbid": [{
+            "bid": [{
+              "id": "TEST",
+              "impid": "1",
+              "price": 10.0,
+              "adid": "1",
+              "adm": "<script src=\"https://assets.a-mo.net/tmode.v1.js\"></script>",
+              "adomain": ["amxrtb.com"],
+              "iurl": "https://assets.a-mo.net/300x250.v2.png",
+              "cid": "1",
+              "crid": "1",
+              "h": 300,
+              "w": 250
+            }]
+          }],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "TEST",
+            "impid": "1",
+            "price": 10.0,
+            "adid": "1",
+            "adm": "<script src=\"https://assets.a-mo.net/tmode.v1.js\"></script>",
+            "adomain": ["amxrtb.com"],
+            "iurl": "https://assets.a-mo.net/300x250.v2.png",
+            "cid": "1",
+            "crid": "1",
+            "h": 300,
+            "w": 250
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/amx/amxtest/exemplary/video-simple.json b/adapters/amx/amxtest/exemplary/video-simple.json
new file mode 100644
index 00000000..8fb3baa2
--- /dev/null
+++ b/adapters/amx/amxtest/exemplary/video-simple.json
@@ -0,0 +1,245 @@
+{
+  "mockBidRequest": {
+    "device": {
+      "dnt": 0,
+      "h": 1120,
+      "ip": "98.249.0.0",
+      "language": "en",
+      "os": "macos",
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+      "w": 1792
+    },
+    "id": "TL3JS6F43CKNDQFY",
+    "imp": [
+      {
+        "video": {
+          "api": [1,2],
+          "boxingallowed": 1,
+          "linearity": 1,
+          "maxduration": 90,
+          "minduration": 6,
+          "mimes": ["video/mp4"],
+          "placement": 1,
+          "playbackmethod": [2],
+          "protocols": [1,2,3,4,5,6,7,8],
+          "skip": 1,
+          "skipafter": 5,
+          "startdelay": 0,
+          "h": 300,
+          "pos": 1,
+          "w": 640
+        },
+        "ext": {
+          "bidder": {
+            "tagId": "cHJlYmlkLm9yZw",
+            "adUnitId": "tagid-override"
+          }
+        },
+        "id": "1",
+        "secure": 1
+      }
+    ],
+    "regs": {
+      "ext": {
+        "gdpr": 0,
+        "us_privacy": "1---"
+      }
+    },
+    "site": {
+      "domain": "www.example.com",
+      "ext": {
+        "amp": 0
+      },
+      "publisher": {
+        "id": "unused_publisher_id"
+      },
+      "page": "https://www.example.com/es6/es6_objects.htm",
+      "ref": "https://www.example.com/es6/es6_objects.htm"
+    },
+    "source": {
+      "ext": {
+        "schain": {
+          "complete": 1,
+          "nodes": [
+            {
+              "asi": "amxrtb.com",
+              "hp": 1,
+              "sid": "1234"
+            }
+          ],
+          "ver": "1.0"
+        }
+      }
+    },
+    "test": 0,
+    "tmax": 300,
+    "user": {
+      "ext": {
+        "eids": [
+          {
+            "source": "amxid",
+            "uids": [
+              {
+                "atype": 1,
+                "id": "88de601e-3d98-48e7-81d7-00000000"
+              }
+            ]
+          }
+        ],
+        "gdpr": 0,
+        "us_privacy": "1---"
+      }
+    }
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://pbs-dev.amxrtb.com/auction/openrtb?v=pbs1.0",
+      "body": {
+        "device": {
+          "dnt": 0,
+          "h": 1120,
+          "ip": "98.249.0.0",
+          "language": "en",
+          "os": "macos",
+          "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+          "w": 1792
+        },
+        "id": "TL3JS6F43CKNDQFY",
+        "imp": [
+          {
+            "video": {
+              "api": [1,2],
+              "boxingallowed": 1,
+              "linearity": 1,
+              "maxduration": 90,
+              "minduration": 6,
+              "mimes": ["video/mp4"],
+              "placement": 1,
+              "playbackmethod": [2],
+              "protocols": [1,2,3,4,5,6,7,8],
+              "skip": 1,
+              "skipafter": 5,
+              "startdelay": 0,
+              "h": 300,
+              "pos": 1,
+              "w": 640
+            },
+            "ext": {
+              "bidder": {
+                "tagId": "cHJlYmlkLm9yZw",
+                "adUnitId": "tagid-override"
+              }
+            },
+            "tagid": "tagid-override",
+            "id": "1",
+            "secure": 1
+          }
+        ],
+        "regs": {
+          "ext": {
+            "gdpr": 0,
+            "us_privacy": "1---"
+          }
+        },
+        "site": {
+          "domain": "www.example.com",
+          "ext": {
+            "amp": 0
+          },
+          "publisher": {
+            "id": "cHJlYmlkLm9yZw"
+          },
+          "page": "https://www.example.com/es6/es6_objects.htm",
+          "ref": "https://www.example.com/es6/es6_objects.htm"
+        },
+        "source": {
+          "ext": {
+            "schain": {
+              "complete": 1,
+              "nodes": [
+                {
+                  "asi": "amxrtb.com",
+                  "hp": 1,
+                  "sid": "1234"
+                }
+              ],
+              "ver": "1.0"
+            }
+          }
+        },
+        "tmax": 300,
+        "user": {
+          "ext": {
+            "eids": [
+              {
+                "source": "amxid",
+                "uids": [
+                  {
+                    "atype": 1,
+                    "id": "88de601e-3d98-48e7-81d7-00000000"
+                  }
+                ]
+              }
+            ],
+            "gdpr": 0,
+            "us_privacy": "1---"
+          }
+        }
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "WQ5V2DWVTMNXABDD",
+        "seatbid": [{
+          "bid": [{
+            "id": "TEST",
+            "impid": "1",
+            "price": 10.0,
+            "adid": "1",
+            "adm": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><VAST version=\"2.0\"><Ad id=\"128a6.44d74.46b3\"><InLine><Error><![CDATA[http://example.net/hbx/verr?e=]]></Error><Impression><![CDATA[http://example.net/hbx/vimp?lid=test&aid=testapp]]></Impression><Creatives><Creative sequence=\"1\"><Linear><Duration>00:00:15</Duration><TrackingEvents><Tracking event=\"firstQuartile\"><![CDATA[https://example.com?event=first_quartile]]></Tracking></TrackingEvents><VideoClicks><ClickThrough><![CDATA[http://example.com]]></ClickThrough></VideoClicks><MediaFiles><MediaFile delivery=\"progressive\" width=\"16\" height=\"9\" type=\"video/mp4\" bitrate=\"800\"><![CDATA[https://example.com/media.mp4]]></MediaFile></MediaFiles></Linear></Creative></Creatives></InLine></Ad></VAST>",
+            "nurl": "https://example.com/nurl",
+            "adomain": ["amxrtb.com"],
+            "iurl": "https://assets.a-mo.net/300x250.v2.png",
+            "cid": "1",
+            "crid": "1",
+            "h": 600,
+            "w": 300,
+            "ext": {
+              "himp": ["https://example.com/imp-tracker/pixel.gif?param=1&param2=2"],
+              "startdelay": 0
+            }
+          }]
+        }],
+        "cur": "USD"
+      }
+    }
+  }],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "TEST",
+            "impid": "1",
+            "price": 10.0,
+            "adid": "1",
+            "adm": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><VAST version=\"2.0\"><Ad id=\"128a6.44d74.46b3\"><InLine><Error><![CDATA[http://example.net/hbx/verr?e=]]></Error><Impression><![CDATA[http://example.net/hbx/vimp?lid=test&aid=testapp]]></Impression><Impression><![CDATA[https://example.com/nurl]]></Impression><Impression><![CDATA[https://example.com/imp-tracker/pixel.gif?param=1&param2=2]]></Impression><Creatives><Creative sequence=\"1\"><Linear><Duration>00:00:15</Duration><TrackingEvents><Tracking event=\"firstQuartile\"><![CDATA[https://example.com?event=first_quartile]]></Tracking></TrackingEvents><VideoClicks><ClickThrough><![CDATA[http://example.com]]></ClickThrough></VideoClicks><MediaFiles><MediaFile delivery=\"progressive\" width=\"16\" height=\"9\" type=\"video/mp4\" bitrate=\"800\"><![CDATA[https://example.com/media.mp4]]></MediaFile></MediaFiles></Linear></Creative></Creatives></InLine></Ad></VAST>",
+            "adomain": ["amxrtb.com"],
+            "iurl": "https://assets.a-mo.net/300x250.v2.png",
+            "cid": "1",
+            "crid": "1",
+            "ext": {
+              "himp": ["https://example.com/imp-tracker/pixel.gif?param=1&param2=2"],
+              "startdelay": 0
+            },
+            "h": 600,
+            "w": 300
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/amx/amxtest/exemplary/web-simple.json b/adapters/amx/amxtest/exemplary/web-simple.json
new file mode 100644
index 00000000..74854f91
--- /dev/null
+++ b/adapters/amx/amxtest/exemplary/web-simple.json
@@ -0,0 +1,246 @@
+{
+  "mockBidRequest": {
+    "device": {
+      "dnt": 0,
+      "h": 1120,
+      "ip": "98.249.0.0",
+      "language": "en",
+      "os": "macos",
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+      "w": 1792
+    },
+    "id": "TL3JS6F43CKNDQFY",
+    "imp": [
+      {
+        "banner": {
+          "format": [
+            {
+              "h": 600,
+              "w": 300
+            }
+          ],
+          "h": 600,
+          "pos": 1,
+          "w": 300
+        },
+        "ext": {
+          "bidder": {
+            "tagId": "cHJlYmlkLm9yZw"
+          }
+        },
+        "tagid": "example-tag-id",
+        "id": "1",
+        "secure": 1
+      }
+    ],
+    "regs": {
+      "ext": {
+        "gdpr": 0,
+        "us_privacy": "1---"
+      }
+    },
+    "site": {
+      "domain": "www.example.com",
+      "ext": {
+        "amp": 0
+      },
+      "publisher": {
+        "id": "unused_publisher_id"
+      },
+      "page": "https://www.example.com/es6/es6_objects.htm",
+      "ref": "https://www.example.com/es6/es6_objects.htm"
+    },
+    "source": {
+      "ext": {
+        "schain": {
+          "complete": 1,
+          "nodes": [
+            {
+              "asi": "amxrtb.com",
+              "hp": 1,
+              "sid": "1234"
+            }
+          ],
+          "ver": "1.0"
+        }
+      }
+    },
+    "test": 0,
+    "tmax": 300,
+    "user": {
+      "ext": {
+        "eids": [
+          {
+            "source": "amxid",
+            "uids": [
+              {
+                "atype": 1,
+                "id": "88de601e-3d98-48e7-81d7-00000000"
+              }
+            ]
+          },
+          {
+            "source": "adserver.org",
+            "uids": [
+              {
+                "id": "1234567",
+                "ext": {
+                  "rtiPartner": "TDID"
+                }
+              }
+            ]
+          }
+        ],
+        "gdpr": 0,
+        "us_privacy": "1---"
+      }
+    }
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://pbs-dev.amxrtb.com/auction/openrtb?v=pbs1.0",
+      "body": {
+        "device": {
+          "dnt": 0,
+          "h": 1120,
+          "ip": "98.249.0.0",
+          "language": "en",
+          "os": "macos",
+          "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+          "w": 1792
+        },
+        "id": "TL3JS6F43CKNDQFY",
+        "imp": [
+          {
+            "tagid": "example-tag-id",
+            "banner": {
+              "format": [
+                {
+                  "h": 600,
+                  "w": 300
+                }
+              ],
+              "h": 600,
+              "pos": 1,
+              "w": 300
+            },
+            "ext": {
+              "bidder": {
+                "tagId": "cHJlYmlkLm9yZw"
+              }
+            },
+            "id": "1",
+            "secure": 1
+          }
+        ],
+        "regs": {
+          "ext": {
+            "gdpr": 0,
+            "us_privacy": "1---"
+          }
+        },
+        "site": {
+          "domain": "www.example.com",
+          "ext": {
+            "amp": 0
+          },
+          "publisher": {
+            "id": "cHJlYmlkLm9yZw"
+          },
+          "page": "https://www.example.com/es6/es6_objects.htm",
+          "ref": "https://www.example.com/es6/es6_objects.htm"
+        },
+        "source": {
+          "ext": {
+            "schain": {
+              "complete": 1,
+              "nodes": [
+                {
+                  "asi": "amxrtb.com",
+                  "hp": 1,
+                  "sid": "1234"
+                }
+              ],
+              "ver": "1.0"
+            }
+          }
+        },
+        "tmax": 300,
+        "user": {
+          "ext": {
+            "eids": [
+              {
+                "source": "amxid",
+                "uids": [
+                  {
+                    "atype": 1,
+                    "id": "88de601e-3d98-48e7-81d7-00000000"
+                  }
+                ]
+              },
+              {
+                "source": "adserver.org",
+                "uids": [
+                  {
+                    "id": "1234567",
+                    "ext": {
+                      "rtiPartner": "TDID"
+                    }
+                  }
+                ]
+              }
+            ],
+            "gdpr": 0,
+            "us_privacy": "1---"
+          }
+        }
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "WQ5V2DWVTMNXABDD",
+        "seatbid": [{
+          "bid": [{
+            "id": "TEST",
+            "impid": "1",
+            "price": 10.0,
+            "adid": "1",
+            "adm": "<script src=\"https://assets.a-mo.net/tmode.v1.js\"></script>",
+            "adomain": ["amxrtb.com"],
+            "iurl": "https://assets.a-mo.net/300x250.v2.png",
+            "cid": "1",
+            "crid": "1",
+            "h": 600,
+            "w": 300
+          }]
+        }],
+        "cur": "USD"
+      }
+    }
+  }],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "TEST",
+            "impid": "1",
+            "price": 10.0,
+            "adid": "1",
+            "adm": "<script src=\"https://assets.a-mo.net/tmode.v1.js\"></script>",
+            "adomain": ["amxrtb.com"],
+            "iurl": "https://assets.a-mo.net/300x250.v2.png",
+            "cid": "1",
+            "crid": "1",
+            "h": 600,
+            "w": 300
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/amx/amxtest/params/race/display.json b/adapters/amx/amxtest/params/race/display.json
new file mode 100644
index 00000000..bd101e95
--- /dev/null
+++ b/adapters/amx/amxtest/params/race/display.json
@@ -0,0 +1,1 @@
+{"tagId":"sample345", "adUnitId": "sampleAdUnitID"}
\ No newline at end of file
diff --git a/adapters/amx/amxtest/params/race/video.json b/adapters/amx/amxtest/params/race/video.json
new file mode 100644
index 00000000..d2f11bf8
--- /dev/null
+++ b/adapters/amx/amxtest/params/race/video.json
@@ -0,0 +1,1 @@
+{"tagId": "sample123", "adUnitId": "sampleAdUnitID"}
\ No newline at end of file
diff --git a/adapters/amx/amxtest/supplemental/204-response.json b/adapters/amx/amxtest/supplemental/204-response.json
new file mode 100644
index 00000000..09571a03
--- /dev/null
+++ b/adapters/amx/amxtest/supplemental/204-response.json
@@ -0,0 +1,109 @@
+{
+  "mockBidRequest": {
+    "device": {
+      "dnt": 0,
+      "h": 1120,
+      "ip": "98.249.0.0",
+      "language": "en",
+      "os": "macos",
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+      "w": 1792
+    },
+    "id": "TL3JS6F43CKNDQFY",
+    "imp": [
+      {
+        "video": {
+          "api": [1,2],
+          "h": 300,
+          "pos": 1,
+          "w": 640
+        },
+        "id": "1",
+        "secure": 1
+      }
+    ],
+    "site": {
+      "ext": {
+        "amp": 0
+      }
+    },
+    "source": {
+      "ext": {
+        "schain": {
+          "complete": 1,
+          "nodes": [
+            {
+              "asi": "amxrtb.com",
+              "hp": 1,
+              "sid": "1234"
+            }
+          ],
+          "ver": "1.0"
+        }
+      }
+    },
+    "test": 0,
+    "tmax": 300
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://pbs-dev.amxrtb.com/auction/openrtb?v=pbs1.0",
+      "body": {
+        "device": {
+          "dnt": 0,
+          "h": 1120,
+          "ip": "98.249.0.0",
+          "language": "en",
+          "os": "macos",
+          "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+          "w": 1792
+        },
+        "id": "TL3JS6F43CKNDQFY",
+        "imp": [
+          {
+            "video": {
+              "api": [1,2],
+              "mimes": null,
+              "h": 300,
+              "pos": 1,
+              "w": 640
+            },
+            "id": "1",
+            "secure": 1
+          }
+        ],
+        "site": {
+          "ext": {
+            "amp": 0
+          }
+        },
+        "source": {
+          "ext": {
+            "schain": {
+              "complete": 1,
+              "nodes": [
+                {
+                  "asi": "amxrtb.com",
+                  "hp": 1,
+                  "sid": "1234"
+                }
+              ],
+              "ver": "1.0"
+            }
+          }
+        },
+        "tmax": 300
+      }
+    },
+    "mockResponse": {
+      "status": 204,
+      "headers": {
+        "X-Nbr": [
+          "3b"
+        ]
+      },
+      "body": {}
+    }
+  }],
+  "expectedMakeBidsErrors": []
+}
diff --git a/adapters/amx/amxtest/supplemental/400-response.json b/adapters/amx/amxtest/supplemental/400-response.json
new file mode 100644
index 00000000..f10cea89
--- /dev/null
+++ b/adapters/amx/amxtest/supplemental/400-response.json
@@ -0,0 +1,114 @@
+{
+  "mockBidRequest": {
+    "device": {
+      "dnt": 0,
+      "h": 1120,
+      "ip": "98.249.0.0",
+      "language": "en",
+      "os": "macos",
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+      "w": 1792
+    },
+    "id": "TL3JS6F43CKNDQFY",
+    "imp": [
+      {
+        "video": {
+          "api": [1,2],
+          "h": 300,
+          "pos": 1,
+          "w": 640
+        },
+        "id": "1",
+        "secure": 1
+      }
+    ],
+    "site": {
+      "ext": {
+        "amp": 0
+      }
+    },
+    "source": {
+      "ext": {
+        "schain": {
+          "complete": 1,
+          "nodes": [
+            {
+              "asi": "amxrtb.com",
+              "hp": 1,
+              "sid": "1234"
+            }
+          ],
+          "ver": "1.0"
+        }
+      }
+    },
+    "test": 0,
+    "tmax": 300
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://pbs-dev.amxrtb.com/auction/openrtb?v=pbs1.0",
+      "body": {
+        "device": {
+          "dnt": 0,
+          "h": 1120,
+          "ip": "98.249.0.0",
+          "language": "en",
+          "os": "macos",
+          "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+          "w": 1792
+        },
+        "id": "TL3JS6F43CKNDQFY",
+        "imp": [
+          {
+            "video": {
+              "api": [1,2],
+              "mimes": null,
+              "h": 300,
+              "pos": 1,
+              "w": 640
+            },
+            "id": "1",
+            "secure": 1
+          }
+        ],
+        "site": {
+          "ext": {
+            "amp": 0
+          }
+        },
+        "source": {
+          "ext": {
+            "schain": {
+              "complete": 1,
+              "nodes": [
+                {
+                  "asi": "amxrtb.com",
+                  "hp": 1,
+                  "sid": "1234"
+                }
+              ],
+              "ver": "1.0"
+            }
+          }
+        },
+        "tmax": 300
+      }
+    },
+    "mockResponse": {
+      "status": 400,
+      "headers": {
+        "X-Nbr": [
+          "3b"
+        ]
+      },
+      "body": {}
+    }
+  }],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Invalid Request: 400. Error Code: 3b",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/amx/amxtest/supplemental/500-response.json b/adapters/amx/amxtest/supplemental/500-response.json
new file mode 100644
index 00000000..fe5d8993
--- /dev/null
+++ b/adapters/amx/amxtest/supplemental/500-response.json
@@ -0,0 +1,114 @@
+{
+  "mockBidRequest": {
+    "device": {
+      "dnt": 0,
+      "h": 1120,
+      "ip": "98.249.0.0",
+      "language": "en",
+      "os": "macos",
+      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+      "w": 1792
+    },
+    "id": "TL3JS6F43CKNDQFY",
+    "imp": [
+      {
+        "video": {
+          "api": [1,2],
+          "h": 300,
+          "pos": 1,
+          "w": 640
+        },
+        "id": "1",
+        "secure": 1
+      }
+    ],
+    "site": {
+      "ext": {
+        "amp": 0
+      }
+    },
+    "source": {
+      "ext": {
+        "schain": {
+          "complete": 1,
+          "nodes": [
+            {
+              "asi": "amxrtb.com",
+              "hp": 1,
+              "sid": "1234"
+            }
+          ],
+          "ver": "1.0"
+        }
+      }
+    },
+    "test": 0,
+    "tmax": 300
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://pbs-dev.amxrtb.com/auction/openrtb?v=pbs1.0",
+      "body": {
+        "device": {
+          "dnt": 0,
+          "h": 1120,
+          "ip": "98.249.0.0",
+          "language": "en",
+          "os": "macos",
+          "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+          "w": 1792
+        },
+        "id": "TL3JS6F43CKNDQFY",
+        "imp": [
+          {
+            "video": {
+              "api": [1,2],
+              "mimes": null,
+              "h": 300,
+              "pos": 1,
+              "w": 640
+            },
+            "id": "1",
+            "secure": 1
+          }
+        ],
+        "site": {
+          "ext": {
+            "amp": 0
+          }
+        },
+        "source": {
+          "ext": {
+            "schain": {
+              "complete": 1,
+              "nodes": [
+                {
+                  "asi": "amxrtb.com",
+                  "hp": 1,
+                  "sid": "1234"
+                }
+              ],
+              "ver": "1.0"
+            }
+          }
+        },
+        "tmax": 300
+      }
+    },
+    "mockResponse": {
+      "status": 500,
+      "headers": {
+        "X-Nbr": [
+          "7a"
+        ]
+      },
+      "body": {}
+    }
+  }],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected response: 500. Error Code: 7a",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/amx/params_test.go b/adapters/amx/params_test.go
new file mode 100644
index 00000000..89e9a3ad
--- /dev/null
+++ b/adapters/amx/params_test.go
@@ -0,0 +1,47 @@
+package amx
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"github.com/stretchr/testify/assert"
+)
+
+var validBidParams = []string{
+	`{"tagId":"sampleTagId", "adUnitId": "sampleAdUnitId"}`,
+	`{"tagId":"sampleTagId", "adUnitId": ""}`,
+	`{"adUnitId": ""}`,
+	`{"adUnitId": "sampleAdUnitId"}`,
+	`{"tagId":"sampleTagId"}`,
+	`{"tagId":""}`,
+	`{}`,
+	`{"otherValue": "ignored"}`,
+	`{"tagId": "sampleTagId", "otherValue": "ignored"}`,
+	`{"otherValue": "ignored", "adUnitId": "sampleAdUnitId"}`,
+}
+
+var invalidBidParams = []string{
+	`{"tagId":1234}`,
+	`{"tagId": true}`,
+	`{"adUnitId": true}`,
+	`{"adUnitId": null}`,
+	`{"adUnitId": null, "tagId": "sampleTagId"}`,
+	`{"adUnitId": 1234, "tagId": "sampleTagId"}`,
+}
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	assert.Nil(t, err)
+	for _, params := range validBidParams {
+		assert.Nil(t, validator.Validate(openrtb_ext.BidderAMX, json.RawMessage(params)))
+	}
+}
+
+func TestInValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	assert.Nil(t, err)
+	for _, params := range invalidBidParams {
+		assert.NotNil(t, validator.Validate(openrtb_ext.BidderAMX, json.RawMessage(params)))
+	}
+}
diff --git a/adapters/amx/usersync_test.go b/adapters/amx/usersync_test.go
new file mode 100644
index 00000000..20a47c33
--- /dev/null
+++ b/adapters/amx/usersync_test.go
@@ -0,0 +1,23 @@
+package amx
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAMXSyncer(t *testing.T) {
+	syncURL := "http://pbs.amxrtb.com/cchain/0?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&cb=localhost%2Fsetuid%3Fbidder%3Damx%26uid%3D"
+	syncURLTemplate := template.Must(template.New("sync-template").Parse(syncURL))
+
+	syncer := NewAMXSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "http://pbs.amxrtb.com/cchain/0?gdpr=&gdpr_consent=&cb=localhost%2Fsetuid%3Fbidder%3Damx%26uid%3D", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.EqualValues(t, 737, syncer.GDPRVendorID())
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/adapters/eplanning/usersync_test.go b/adapters/eplanning/usersync_test.go
index 890832ba..85770689 100644
--- a/adapters/eplanning/usersync_test.go
+++ b/adapters/eplanning/usersync_test.go
@@ -20,6 +20,6 @@ func TestEPlanningSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ads.us.e-planning.net/uspd/1/?du=https%3A%2F%2Fads.us.e-planning.net%2Fgetuid%2F1%2F5a1ad71d2d53a0f5%3Flocalhost%2Fsetuid%3Fbidder%3Deplanning%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
+	assert.EqualValues(t, 90, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/nobid/nobid_test.go b/adapters/nobid/nobid_test.go
new file mode 100644
index 00000000..cb0e8e71
--- /dev/null
+++ b/adapters/nobid/nobid_test.go
@@ -0,0 +1,12 @@
+package nobid
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+func TestJsonSamples(t *testing.T) {
+	nobidAdapter := NewNoBidBidder("http://ads.servenobid.com/ortb_adreq?tek=pbs")
+	adapterstest.RunJSONBidderTest(t, "nobidtest", nobidAdapter)
+}
diff --git a/adapters/nobid/nobidtest/exemplary/banner.json b/adapters/nobid/nobidtest/exemplary/banner.json
new file mode 100644
index 00000000..914eaf24
--- /dev/null
+++ b/adapters/nobid/nobidtest/exemplary/banner.json
@@ -0,0 +1,84 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "banner": {
+            "format": [{"w": 728, "h": 90}]
+          },
+          "ext": {
+            "nobid": {
+              "siteId": "21863532377"
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "id":"test-imp-id",
+                "banner": {
+                  "format": [{"w": 728, "h": 90}]
+                },
+                "ext": {
+                  "nobid": {
+                    "siteId": "21863532377"
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "test-request-id",
+            "seatbid": [
+              {
+                "seat": "ttx",
+                "bid": [{
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "test-imp-id",
+                  "price": 0.500000,
+                  "adm": "some-test-ad",
+                  "crid": "crid_10",
+                  "h": 90,
+                  "w": 728
+                }]
+              }
+            ],
+            "cur": "USD"
+          }
+        }
+      }
+    ],
+  
+    "expectedBidResponses": [
+      {
+        "currency": "USD",
+        "bids": [
+          {
+            "bid": {
+              "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+              "impid": "test-imp-id",
+              "price": 0.5,
+              "adm": "some-test-ad",
+              "crid": "crid_10",
+              "w": 728,
+              "h": 90
+            },
+            "type": "banner"
+          }
+        ]
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/bad-mediatype.json b/adapters/nobid/nobidtest/supplemental/bad-mediatype.json
new file mode 100644
index 00000000..6b07d597
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/bad-mediatype.json
@@ -0,0 +1,47 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "Xbanner": {
+            "format": [{"w": 728, "h": 90}]
+          },
+          "ext": {
+            "nobid": {
+              "siteId": "21863532377"
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "id":"test-imp-id",
+                "ext": {
+                  "nobid": {
+                    "siteId": "21863532377"
+                  }
+                }
+              }
+            ]
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+      {
+      "value": "Unexpected status code: 0. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/bad-request.json b/adapters/nobid/nobidtest/supplemental/bad-request.json
new file mode 100644
index 00000000..00d0f404
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/bad-request.json
@@ -0,0 +1,51 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+          {
+            "id": "test-imp-id",
+            "banner": {
+              "format": [{"w": 728, "h": 90}]
+            },
+            "ext": {
+              "nobid": {
+                "siteId": "000"
+              }
+            }
+          }
+        ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+            "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+            "body": {
+              "id": "test-request-id",
+              "imp": [
+                {
+                  "id":"test-imp-id",
+                  "banner": {
+                    "format": [{"w": 728, "h": 90}]
+                  },
+                  "ext": {
+                    "nobid": {
+                      "siteId": "000"
+                    }
+                  }
+                }
+              ]
+            }
+        },
+        "mockResponse": {
+          "status": 400
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+            "comparison": "literal"
+        }
+    ]
+  }
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/bad-response.json b/adapters/nobid/nobidtest/supplemental/bad-response.json
new file mode 100644
index 00000000..05b6e623
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/bad-response.json
@@ -0,0 +1,71 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "banner": {
+            "format": [{"w": 728, "h": 90}]
+          },
+          "ext": {
+            "nobid": {
+              "siteId": "21863532377"
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "id":"test-imp-id",
+                "banner": {
+                  "format": [{"w": 728, "h": 90}]
+                },
+                "ext": {
+                  "nobid": {
+                    "siteId": "21863532377"
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "XX",
+            "seatbid": [
+              {
+                "seat": "ttx",
+                "bid": [{
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "XYZ",
+                  "price": 0.500000,
+                  "adm": "some-test-ad",
+                  "crid": "crid_10",
+                  "h": 90,
+                  "w": 728
+                }]
+              }
+            ],
+            "cur": "USD"
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+      {
+      "value": "Failed to find impression \"XYZ\"",
+      "comparison": "literal"
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/missing-imps.json b/adapters/nobid/nobidtest/supplemental/missing-imps.json
new file mode 100644
index 00000000..93775160
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/missing-imps.json
@@ -0,0 +1,14 @@
+{
+    "expectedMakeRequestsErrors": [
+        {
+          "value": "No Imps in Bid Request",
+          "comparison": "literal"
+        }
+    ],
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": []
+    },
+    "httpCalls": []
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/no-content.json b/adapters/nobid/nobidtest/supplemental/no-content.json
new file mode 100644
index 00000000..a81ca5bd
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/no-content.json
@@ -0,0 +1,46 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+          {
+            "id": "test-imp-id",
+            "banner": {
+              "format": [{"w": 728, "h": 90}]
+            },
+            "ext": {
+              "nobid": {
+                "siteId": "000"
+              }
+            }
+          }
+        ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+            "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+            "body": {
+              "id": "test-request-id",
+              "imp": [
+                {
+                  "id":"test-imp-id",
+                  "banner": {
+                    "format": [{"w": 728, "h": 90}]
+                  },
+                  "ext": {
+                    "nobid": {
+                      "siteId": "000"
+                    }
+                  }
+                }
+              ]
+            }
+        },
+        "mockResponse": {
+          "status": 204
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": []
+  }
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/notok-response.json b/adapters/nobid/nobidtest/supplemental/notok-response.json
new file mode 100644
index 00000000..ea9d380d
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/notok-response.json
@@ -0,0 +1,51 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+          {
+            "id": "test-imp-id",
+            "banner": {
+              "format": [{"w": 728, "h": 90}]
+            },
+            "ext": {
+              "nobid": {
+                "siteId": "000"
+              }
+            }
+          }
+        ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+            "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+            "body": {
+              "id": "test-request-id",
+              "imp": [
+                {
+                  "id":"test-imp-id",
+                  "banner": {
+                    "format": [{"w": 728, "h": 90}]
+                  },
+                  "ext": {
+                    "nobid": {
+                      "siteId": "000"
+                    }
+                  }
+                }
+              ]
+            }
+        },
+        "mockResponse": {
+          "status": 500
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Unexpected status code: 500. Run with request.debug = 1 for more info",
+            "comparison": "literal"
+        }
+    ]
+  }
\ No newline at end of file
diff --git a/adapters/nobid/params_test.go b/adapters/nobid/params_test.go
new file mode 100644
index 00000000..75d69943
--- /dev/null
+++ b/adapters/nobid/params_test.go
@@ -0,0 +1,53 @@
+package nobid
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderNoBid, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected nobid params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderNoBid, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"siteId": 25251, "bidfloor": 0.01}`,
+}
+
+var invalidParams = []string{
+	`null`,
+	`nil`,
+	``,
+	`[]`,
+	`true`,
+	`{}`,
+	`{"tagid":12345678}`,
+	`{"tagId":"12345678"}`,
+	`{"tagid":"25251", "bidfloor": 0.01}`,
+	`{"tagId": 12345678}`,
+	`{"placementId": "1"}`,
+	`{"placementId": 1}`,
+}
diff --git a/adapters/nobid/usersync_test.go b/adapters/nobid/usersync_test.go
new file mode 100644
index 00000000..bc55d130
--- /dev/null
+++ b/adapters/nobid/usersync_test.go
@@ -0,0 +1,34 @@
+package nobid
+
+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 TestNoBidSyncer(t *testing.T) {
+	syncURL := "https://ads.servenobid.com/sync?tek=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect=localhost%2Fsetuid%3Fbidder%3Dtest_bidder%26uid%3D%24UID"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewNoBidSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "1",
+			Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA",
+		},
+		CCPA: ccpa.Policy{
+			Consent: "1NYN",
+		},
+	})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "https://ads.servenobid.com/sync?tek=pbs&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redirect=localhost%2Fsetuid%3Fbidder%3Dtest_bidder%26uid%3D%24UID", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/adapters/silvermob/params_test.go b/adapters/silvermob/params_test.go
new file mode 100644
index 00000000..13009f6a
--- /dev/null
+++ b/adapters/silvermob/params_test.go
@@ -0,0 +1,56 @@
+package silvermob
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// TestValidParams makes sure that the silvermob schema accepts all imp.ext fields which we intend to support.
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderSilverMob, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected silvermob params: %s", validParam)
+		}
+	}
+}
+
+// TestInvalidParams makes sure that the silvermob schema rejects all the imp.ext fields we don't support.
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderSilverMob, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"zoneid": "16", "host": "us"}`,
+	`{"zoneid": "16", "host": "eu"}`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"ZoneID": "asd", "Host": "123"}`,
+	`{}`,
+	`{"ZoneID": "asd"}`,
+	`{"Host": "111"}`,
+	`{"zoneid": 16, "host": 111}`,
+}
diff --git a/adapters/silvermob/silvermob_test.go b/adapters/silvermob/silvermob_test.go
new file mode 100644
index 00000000..f75b16fe
--- /dev/null
+++ b/adapters/silvermob/silvermob_test.go
@@ -0,0 +1,11 @@
+package silvermob
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "silvermobtest", NewSilverMobBidder("http://{{.Host}}.example.com/api/dsp/bid/{{.ZoneID}}"))
+}
diff --git a/adapters/silvermob/silvermobtest/exemplary/banner-app.json b/adapters/silvermob/silvermobtest/exemplary/banner-app.json
new file mode 100644
index 00000000..7a2a4fef
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/exemplary/banner-app.json
@@ -0,0 +1,163 @@
+{
+    "mockBidRequest": {
+      "id": "some-request-id",
+      "device": {
+        "ua": "test-user-agent",
+        "ip": "123.123.123.123",
+        "language": "en",
+        "dnt": 0
+      },
+      "tmax": 1000,
+      "user": {
+        "buyeruid": "awesome-user"
+      },
+      "app": {
+        "publisher": {
+          "id": "123456789"
+        },
+        "cat": [
+          "IAB22-1"
+        ],
+        "bundle": "com.app.awesome",
+        "name": "Awesome App",
+        "domain": "awesomeapp.com",
+        "id": "123456789"
+      },
+      "imp": [
+        {
+          "id": "some-impression-id",
+          "tagid": "ogTAGID",
+          "banner": {
+            "w":320,
+            "h":50
+          },
+          "ext": {
+            "bidder": {
+              "host": "eu",
+              "zoneid": "0"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "headers": {
+            "Content-Type": [
+              "application/json;charset=utf-8"
+            ],
+            "Accept": [
+              "application/json"
+            ],
+            "X-Openrtb-Version": [
+              "2.5"
+            ],
+            "User-Agent": [
+              "test-user-agent"
+            ],
+            "X-Forwarded-For": [
+              "123.123.123.123"
+            ]
+          },
+          "uri": "http://eu.example.com/api/dsp/bid/0",
+          "body": {
+            "id": "some-request-id",
+            "device": {
+              "ua": "test-user-agent",
+              "ip": "123.123.123.123",
+              "language": "en",
+              "dnt": 0
+            },
+            "imp": [
+              {
+                "id": "some-impression-id",
+                "banner": {
+                    "w":320,
+                    "h":50
+                },
+                "tagid": "ogTAGID",
+                "ext": {
+                  "bidder": {
+                    "host": "eu",
+                    "zoneid": "0"
+                  }
+                }
+              }
+            ],
+            "app": {
+              "id": "123456789",
+              "name": "Awesome App",
+              "bundle": "com.app.awesome",
+              "domain": "awesomeapp.com",
+              "cat": [
+                "IAB22-1"
+              ],
+              "publisher": {
+                "id": "123456789"
+              }
+            },
+            "user": {
+              "buyeruid": "awesome-user"
+            },
+            "tmax": 1000
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "awesome-resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+                    "impid": "1",
+                    "price": 3.5,
+                    "adm": "awesome-markup",
+                    "adomain": [
+                      "awesome.com"
+                    ],
+                    "crid": "20",
+                    "w":320,
+                    "h":50
+                  }
+                ],
+              "type": "banner",
+                "seat": "silvermob"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "silvermob": 154
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [ 
+      {
+        "bids":[
+          {
+            "bid":{
+              "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+              "impid": "1",
+              "price": 3.5,
+              "adm": "awesome-markup",
+              "adomain": [
+                "awesome.com"
+              ],
+              "crid": "20",
+              "w":320,
+              "h":50
+            },
+            "type": "banner"
+          }
+        ]
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/silvermob/silvermobtest/exemplary/banner-multi-app.json b/adapters/silvermob/silvermobtest/exemplary/banner-multi-app.json
new file mode 100644
index 00000000..531704c5
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/exemplary/banner-multi-app.json
@@ -0,0 +1,293 @@
+{
+    "mockBidRequest": {
+      "id": "some-request-id",
+      "device": {
+        "ua": "test-user-agent",
+        "ip": "123.123.123.123",
+        "language": "en",
+        "dnt": 0
+      },
+      "tmax": 1000,
+      "user": {
+        "buyeruid": "awesome-user"
+      },
+      "app": {
+        "publisher": {
+          "id": "123456789"
+        },
+        "cat": [
+          "IAB22-1"
+        ],
+        "bundle": "com.app.awesome",
+        "name": "Awesome App",
+        "domain": "awesomeapp.com",
+        "id": "123456789"
+      },
+      "imp": [
+        {
+          "id": "some-impression-id",
+          "tagid": "ogTAGID",
+          "banner": {
+            "w":320,
+            "h":50
+          },
+          "ext": {
+            "bidder": {
+              "host": "eu",
+              "zoneid": "0"
+            }
+          }
+        },
+        {
+            "id": "another-impression-id",
+            "tagid": "ogTAGID",
+            "banner": {
+              "w":320,
+              "h":480
+            },
+            "ext": {
+              "bidder": {
+                "host": "eu",
+                "zoneid": "1"
+              }
+            }
+          }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "headers": {
+            "Content-Type": [
+              "application/json;charset=utf-8"
+            ],
+            "Accept": [
+              "application/json"
+            ],
+            "X-Openrtb-Version": [
+              "2.5"
+            ],
+            "User-Agent": [
+              "test-user-agent"
+            ],
+            "X-Forwarded-For": [
+              "123.123.123.123"
+            ]
+          },
+          "uri": "http://eu.example.com/api/dsp/bid/0",
+          "body": {
+            "id": "some-request-id",
+            "device": {
+              "ua": "test-user-agent",
+              "ip": "123.123.123.123",
+              "language": "en",
+              "dnt": 0
+            },
+            "imp": [
+              {
+                "id": "some-impression-id",
+                "banner": {
+                    "w":320,
+                    "h":50
+                },
+                "tagid": "ogTAGID",
+                "ext": {
+                  "bidder": {
+                    "host": "eu",
+                    "zoneid": "0"
+                  }
+                }
+              }
+            ],
+            "app": {
+              "id": "123456789",
+              "name": "Awesome App",
+              "bundle": "com.app.awesome",
+              "domain": "awesomeapp.com",
+              "cat": [
+                "IAB22-1"
+              ],
+              "publisher": {
+                "id": "123456789"
+              }
+            },
+            "user": {
+              "buyeruid": "awesome-user"
+            },
+            "tmax": 1000
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "awesome-resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+                    "impid": "some-impression-id",
+                    "price": 3.5,
+                    "adm": "awesome-markup",
+                    "adomain": [
+                      "awesome.com"
+                    ],
+                    "crid": "20",
+                    "w":320,
+                    "h":50
+                  }
+                ],
+              "type": "banner",
+                "seat": "silvermob"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "silvermob": 154
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      },
+      {
+        "expectedRequest": {
+          "headers": {
+            "Content-Type": [
+              "application/json;charset=utf-8"
+            ],
+            "Accept": [
+              "application/json"
+            ],
+            "X-Openrtb-Version": [
+              "2.5"
+            ],
+            "User-Agent": [
+              "test-user-agent"
+            ],
+            "X-Forwarded-For": [
+              "123.123.123.123"
+            ]
+          },
+          "uri": "http://eu.example.com/api/dsp/bid/1",
+          "body": {
+            "id": "some-request-id",
+            "device": {
+              "ua": "test-user-agent",
+              "ip": "123.123.123.123",
+              "language": "en",
+              "dnt": 0
+            },
+            "imp": [
+              {
+                "id": "another-impression-id",
+                "banner": {
+                    "w":320,
+                    "h":480
+                },
+                "tagid": "ogTAGID",
+                "ext": {
+                  "bidder": {
+                    "host": "eu",
+                    "zoneid": "1"
+                  }
+                }
+              }
+            ],
+            "app": {
+              "id": "123456789",
+              "name": "Awesome App",
+              "bundle": "com.app.awesome",
+              "domain": "awesomeapp.com",
+              "cat": [
+                "IAB22-1"
+              ],
+              "publisher": {
+                "id": "123456789"
+              }
+            },
+            "user": {
+              "buyeruid": "awesome-user"
+            },
+            "tmax": 1000
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "awesome-resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "a3ae1b4e2fc24a4fb45540082e98e162",
+                    "impid": "another-impression-id",
+                    "price": 3.5,
+                    "adm": "awesome-markup",
+                    "adomain": [
+                      "awesome.com"
+                    ],
+                    "crid": "21",
+                    "w":320,
+                    "h":480
+                  }
+                ],
+              "type": "banner",
+                "seat": "silvermob"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "silvermob": 154
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [ 
+        
+      {
+        "bids":[
+          {
+            "bid":{
+              "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+              "impid": "some-impression-id",
+              "price": 3.5,
+              "adm": "awesome-markup",
+              "adomain": [
+                "awesome.com"
+              ],
+              "crid": "20",
+              "w":320,
+              "h":50
+            },
+            "type": "banner"
+          }
+        ]
+      },
+      {
+        "bids": [
+            {
+                "bid":{
+                  "id": "a3ae1b4e2fc24a4fb45540082e98e162",
+                  "impid": "another-impression-id",
+                  "price": 3.5,
+                  "adm": "awesome-markup",
+                  "adomain": [
+                    "awesome.com"
+                  ],
+                  "crid": "21",
+                  "w":320,
+                  "h":480
+                },
+                "type": "banner"
+              }
+        ]
+    }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/silvermob/silvermobtest/exemplary/native-app.json b/adapters/silvermob/silvermobtest/exemplary/native-app.json
new file mode 100644
index 00000000..49934bf7
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/exemplary/native-app.json
@@ -0,0 +1,159 @@
+{
+    "mockBidRequest": {
+      "id": "some-request-id",
+      "device": {
+        "ua": "test-user-agent",
+        "ip": "123.123.123.123",
+        "language": "en",
+        "dnt": 0
+      },
+      "tmax": 1000,
+      "user": {
+        "buyeruid": "awesome-user"
+      },
+      "app": {
+        "publisher": {
+          "id": "123456789"
+        },
+        "cat": [
+          "IAB22-1"
+        ],
+        "bundle": "com.app.awesome",
+        "name": "Awesome App",
+        "domain": "awesomeapp.com",
+        "id": "123456789"
+      },
+      "imp": [
+        {
+          "id": "some-impression-id",
+          "tagid": "ogTAGID",
+          "native": {
+            "ver":"1.1",
+            "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+          },
+          "ext": {
+            "bidder": {
+              "host": "eu",
+              "zoneid": "0"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "headers": {
+            "Content-Type": [
+              "application/json;charset=utf-8"
+            ],
+            "Accept": [
+              "application/json"
+            ],
+            "X-Openrtb-Version": [
+              "2.5"
+            ],
+            "User-Agent": [
+              "test-user-agent"
+            ],
+            "X-Forwarded-For": [
+              "123.123.123.123"
+            ]
+          },
+          "uri": "http://eu.example.com/api/dsp/bid/0",
+          "body": {
+            "id": "some-request-id",
+            "device": {
+              "ua": "test-user-agent",
+              "ip": "123.123.123.123",
+              "language": "en",
+              "dnt": 0
+            },
+            "imp": [
+              {
+                "id": "some-impression-id",
+                "native": {
+                  "ver":"1.1",
+                  "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+                },
+                "tagid": "ogTAGID",
+                "ext": {
+                  "bidder": {
+                    "host": "eu",
+                    "zoneid": "0"
+                  }
+                }
+              }
+            ],
+            "app": {
+              "id": "123456789",
+              "name": "Awesome App",
+              "bundle": "com.app.awesome",
+              "domain": "awesomeapp.com",
+              "cat": [
+                "IAB22-1"
+              ],
+              "publisher": {
+                "id": "123456789"
+              }
+            },
+            "user": {
+              "buyeruid": "awesome-user"
+            },
+            "tmax": 1000
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "awesome-resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+                    "impid": "some-impression-id",
+                    "price": 3.5,
+                    "adm": "asesome-markup",
+                    "adomain": [
+                      "awesome.com"
+                    ],
+                    "crid": "20"
+                  }
+                ],
+                "type": "native",
+                "seat": "silvermob"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "silvermob": 154
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [
+      {
+        "bids":[
+          {
+            "bid":  {
+              "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+              "impid": "some-impression-id",
+              "price": 3.5,
+              "adm": "asesome-markup",
+              "crid": "20",
+              "adomain": [
+                "awesome.com"
+              ]
+            },
+            "type": "native"
+          }
+        ]
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/silvermob/silvermobtest/exemplary/video-app.json b/adapters/silvermob/silvermobtest/exemplary/video-app.json
new file mode 100644
index 00000000..c80d5ab9
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/exemplary/video-app.json
@@ -0,0 +1,171 @@
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.awesome",
+      "name": "Awesome App",
+      "domain": "awesomeapp.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://eu.example.com/api/dsp/bid/0",
+        "body": {
+          "id": "some-request-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "some-impression-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "ogTAGID",
+              "ext": {
+                "bidder": {
+                  "host": "eu",
+                  "zoneid": "0"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "123456789",
+            "name": "Awesome App",
+            "bundle": "com.app.awesome",
+            "domain": "awesomeapp.com",
+            "cat": [
+              "IAB22-1"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "awesome-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "awesome-resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+                  "impid": "some-impression-id",
+                  "price": 3.5,
+                  "adm": "asesome-markup",
+                  "adomain": [
+                    "awesome.com"
+                  ],
+                  "crid": "20",
+                  "w": 1280,
+                  "h": 720
+                }
+              ],
+              "seat": "silvermob"
+            }
+          ],
+          "cur": "USD",
+          "ext": {
+            "responsetimemillis": {
+              "silvermob": 154
+            },
+            "tmaxrequest": 1000
+          }
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "bids":[
+        {
+          "bid":  {
+            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+            "impid": "some-impression-id",
+            "price": 3.5,
+            "adm": "asesome-markup",
+            "crid": "20",
+            "adomain": [
+              "awesome.com"
+            ],
+            "w": 1280,
+            "h": 720
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/silvermob/silvermobtest/params/race/banner.json b/adapters/silvermob/silvermobtest/params/race/banner.json
new file mode 100644
index 00000000..9b6ca9d7
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/params/race/banner.json
@@ -0,0 +1,4 @@
+{
+  "zoneid": "0",
+  "host": "eu"
+}
diff --git a/adapters/silvermob/silvermobtest/params/race/native.json b/adapters/silvermob/silvermobtest/params/race/native.json
new file mode 100644
index 00000000..f63a4842
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/params/race/native.json
@@ -0,0 +1,4 @@
+{
+  "zoneid": "0",
+  "host": "eu"
+}
\ No newline at end of file
diff --git a/adapters/silvermob/silvermobtest/params/race/video.json b/adapters/silvermob/silvermobtest/params/race/video.json
new file mode 100644
index 00000000..f63a4842
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/params/race/video.json
@@ -0,0 +1,4 @@
+{
+  "zoneid": "0",
+  "host": "eu"
+}
\ No newline at end of file
diff --git a/adapters/silvermob/silvermobtest/supplemental/empty-seatbid-array.json b/adapters/silvermob/silvermobtest/supplemental/empty-seatbid-array.json
new file mode 100644
index 00000000..be95abea
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/empty-seatbid-array.json
@@ -0,0 +1,139 @@
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.awesome",
+      "name": "Awesome App",
+      "domain": "awesomeapp.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ],
+          "X-Openrtb-Version": [
+            "2.5"
+          ],
+          "User-Agent": [
+            "test-user-agent"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ]
+        },
+        "uri": "http://eu.example.com/api/dsp/bid/0",
+        "body": {
+          "id": "some-request-id",
+          "device": {
+            "ua": "test-user-agent",
+            "ip": "123.123.123.123",
+            "language": "en",
+            "dnt": 0
+          },
+          "imp": [
+            {
+              "id": "some-impression-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 120,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "ogTAGID",
+              "ext": {
+                "bidder": {
+                  "host": "eu",
+                  "zoneid": "0"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "123456789",
+            "name": "Awesome App",
+            "bundle": "com.app.awesome",
+            "domain": "awesomeapp.com",
+            "cat": [
+              "IAB22-1"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "buyeruid": "awesome-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "awesome-resp-id",
+          "seatbid": [
+          ],
+          "cur": "USD",
+          "ext": {
+            "responsetimemillis": {
+              "silvermob": 154
+            },
+            "tmaxrequest": 1000
+          }
+        }
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Empty SeatBid array",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/silvermob/silvermobtest/supplemental/invalid-response.json b/adapters/silvermob/silvermobtest/supplemental/invalid-response.json
new file mode 100644
index 00000000..d2a1e890
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/invalid-response.json
@@ -0,0 +1,118 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.awesome",
+      "name": "Awesome App",
+      "domain": "awesomeapp.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "banner": {
+          "w":320,
+          "h":50
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": [
+          "application/json;charset=utf-8"
+        ],
+        "Accept": [
+          "application/json"
+        ],
+        "X-Openrtb-Version": [
+          "2.5"
+        ],
+        "User-Agent": [
+          "test-user-agent"
+        ],
+        "X-Forwarded-For": [
+          "123.123.123.123"
+        ]
+      },
+      "uri": "http://eu.example.com/api/dsp/bid/0",
+      "body": {
+        "id": "some-request-id",
+        "device": {
+          "ua": "test-user-agent",
+          "ip": "123.123.123.123",
+          "language": "en",
+          "dnt": 0
+        },
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "banner": {
+                "w":320,
+                "h":50
+            },
+            "tagid": "ogTAGID",
+            "ext": {
+              "bidder": {
+                "host": "eu",
+                "zoneid": "0"
+              }
+            }
+          }
+        ],
+        "app": {
+          "id": "123456789",
+          "name": "Awesome App",
+          "bundle": "com.app.awesome",
+          "domain": "awesomeapp.com",
+          "cat": [
+            "IAB22-1"
+          ],
+          "publisher": {
+            "id": "123456789"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": "invalid response"
+    }
+  }],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Error unmarshaling server Response: json: cannot unmarshal string into Go value of type openrtb.BidResponse",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/silvermob/silvermobtest/supplemental/invalid-silvermob-ext-object.json b/adapters/silvermob/silvermobtest/supplemental/invalid-silvermob-ext-object.json
new file mode 100644
index 00000000..090d7aff
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/invalid-silvermob-ext-object.json
@@ -0,0 +1,28 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "my-adcode",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": "Awesome"
+      }
+    ],
+    "site": {
+      "page": "test.com"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value":  "error unmarshaling imp.ext: json: cannot unmarshal string into Go value of type adapters.ExtImpBidder",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/silvermob/silvermobtest/supplemental/status-code-bad-request.json b/adapters/silvermob/silvermobtest/supplemental/status-code-bad-request.json
new file mode 100644
index 00000000..e93f2490
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/status-code-bad-request.json
@@ -0,0 +1,99 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.awesome",
+      "name": "Awesome App",
+      "domain": "awesomeapp.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://eu.example.com/api/dsp/bid/0",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "tagid": "ogTAGID",
+            "ext": {
+              "bidder": {
+                "host": "eu",
+                "zoneid": "0"
+              }
+            }
+          }
+        ],
+        "app":  {
+          "publisher": {
+            "id": "123456789"
+          },
+          "cat": [
+            "IAB22-1"
+          ],
+          "bundle": "com.app.awesome",
+          "name": "Awesome App",
+          "domain": "awesomeapp.com",
+          "id": "123456789"
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 400
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad Request status code: 400. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/silvermob/silvermobtest/supplemental/status-code-no-content.json b/adapters/silvermob/silvermobtest/supplemental/status-code-no-content.json
new file mode 100644
index 00000000..a29710bf
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/status-code-no-content.json
@@ -0,0 +1,83 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "id": "app_001",
+      "bundle": "com.awesome.app",
+      "publisher": {
+        "id": "2"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://eu.example.com/api/dsp/bid/0",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "ogTAGID",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "bidder": {
+                "host": "eu",
+                "zoneid": "0"
+              }
+            }
+          }
+        ],
+        "app": {
+          "id": "app_001",
+          "bundle": "com.awesome.app",
+          "publisher": {
+            "id": "2"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 204,
+      "body": {}
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": []
+}
diff --git a/adapters/silvermob/silvermobtest/supplemental/status-code-other-error.json b/adapters/silvermob/silvermobtest/supplemental/status-code-other-error.json
new file mode 100644
index 00000000..a32af01e
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/status-code-other-error.json
@@ -0,0 +1,87 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "id": "app_001",
+      "bundle": "com.awesome.app",
+      "publisher": {
+        "id": "2"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://eu.example.com/api/dsp/bid/0",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "ogTAGID",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "bidder": {
+                "host": "eu",
+                "zoneid": "0"
+              }
+            }
+          }
+        ],
+        "app": {
+          "id": "app_001",
+          "bundle": "com.awesome.app",
+          "publisher": {
+            "id": "2"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 306
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 306. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/silvermob/silvermobtest/supplemental/status-code-service-unavailable.json b/adapters/silvermob/silvermobtest/supplemental/status-code-service-unavailable.json
new file mode 100644
index 00000000..5772a86e
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/status-code-service-unavailable.json
@@ -0,0 +1,87 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "id": "app_001",
+      "bundle": "com.awesome.app",
+      "publisher": {
+        "id": "2"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "host": "eu",
+            "zoneid": "0"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "http://eu.example.com/api/dsp/bid/0",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "ogTAGID",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "bidder": {
+                "host": "eu",
+                "zoneid": "0"
+              }
+            }
+          }
+        ],
+        "app": {
+          "id": "app_001",
+          "bundle": "com.awesome.app",
+          "publisher": {
+            "id": "2"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 503
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 503. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/config/accounts_test.go b/config/accounts_test.go
new file mode 100644
index 00000000..ca7e8938
--- /dev/null
+++ b/config/accounts_test.go
@@ -0,0 +1,116 @@
+package config
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAccountGDPREnabledForIntegrationType(t *testing.T) {
+	trueValue, falseValue := true, false
+
+	tests := []struct {
+		description          string
+		giveIntegrationType  IntegrationType
+		giveGDPREnabled      *bool
+		giveAMPGDPREnabled   *bool
+		giveAppGDPREnabled   *bool
+		giveVideoGDPREnabled *bool
+		giveWebGDPREnabled   *bool
+		wantEnabled          *bool
+	}{
+		{
+			description:         "GDPR AMP integration enabled, general GDPR disabled",
+			giveIntegrationType: IntegrationTypeAMP,
+			giveGDPREnabled:     &falseValue,
+			giveAMPGDPREnabled:  &trueValue,
+			wantEnabled:         &trueValue,
+		},
+		{
+			description:         "GDPR App integration enabled, general GDPR disabled",
+			giveIntegrationType: IntegrationTypeApp,
+			giveGDPREnabled:     &falseValue,
+			giveAppGDPREnabled:  &trueValue,
+			wantEnabled:         &trueValue,
+		},
+		{
+			description:          "GDPR Video integration enabled, general GDPR disabled",
+			giveIntegrationType:  IntegrationTypeVideo,
+			giveGDPREnabled:      &falseValue,
+			giveVideoGDPREnabled: &trueValue,
+			wantEnabled:          &trueValue,
+		},
+		{
+			description:         "GDPR Web integration enabled, general GDPR disabled",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     &falseValue,
+			giveWebGDPREnabled:  &trueValue,
+			wantEnabled:         &trueValue,
+		},
+		{
+			description:         "Web integration enabled, general GDPR unspecified",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     nil,
+			giveWebGDPREnabled:  &trueValue,
+			wantEnabled:         &trueValue,
+		},
+		{
+			description:         "GDPR Web integration disabled, general GDPR enabled",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     &trueValue,
+			giveWebGDPREnabled:  &falseValue,
+			wantEnabled:         &falseValue,
+		},
+		{
+			description:         "GDPR Web integration disabled, general GDPR unspecified",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     nil,
+			giveWebGDPREnabled:  &falseValue,
+			wantEnabled:         &falseValue,
+		},
+		{
+			description:         "GDPR Web integration unspecified, general GDPR disabled",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     &falseValue,
+			giveWebGDPREnabled:  nil,
+			wantEnabled:         &falseValue,
+		},
+		{
+			description:         "GDPR Web integration unspecified, general GDPR enabled",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     &trueValue,
+			giveWebGDPREnabled:  nil,
+			wantEnabled:         &trueValue,
+		},
+		{
+			description:         "GDPR Web integration unspecified, general GDPR unspecified",
+			giveIntegrationType: IntegrationTypeWeb,
+			giveGDPREnabled:     nil,
+			giveWebGDPREnabled:  nil,
+			wantEnabled:         nil,
+		},
+	}
+
+	for _, tt := range tests {
+		account := Account{
+			GDPR: AccountGDPR{
+				Enabled: tt.giveGDPREnabled,
+				IntegrationEnabled: AccountGDPRIntegration{
+					AMP:   tt.giveAMPGDPREnabled,
+					App:   tt.giveAppGDPREnabled,
+					Video: tt.giveVideoGDPREnabled,
+					Web:   tt.giveWebGDPREnabled,
+				},
+			},
+		}
+
+		enabled := account.GDPR.EnabledForIntegrationType(tt.giveIntegrationType)
+
+		if tt.wantEnabled == nil {
+			assert.Nil(t, enabled, tt.description)
+		} else {
+			assert.NotNil(t, enabled, tt.description)
+			assert.Equal(t, *tt.wantEnabled, *enabled, tt.description)
+		}
+	}
+}
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index 33411c87..66a3bd67 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -1351,7 +1351,7 @@ func (m *mockExchangeVideo) HoldAuction(ctx context.Context, bidRequest *openrtb
 	if debugLog != nil && debugLog.Enabled {
 		m.cache.called = true
 	}
-	ext := []byte(`{"prebid":{"targeting":{"hb_bidder_appnexus":"appnexus","hb_pb_appnexus":"20.00","hb_pb_cat_dur_appnex":"20.00_395_30s","hb_size":"1x1", "hb_uuid_appnexus":"837ea3b7-5598-4958-8c45-8e9ef2bf7cc1"},"type":"video"},"bidder":{"appnexus":{"brand_id":1,"auction_id":7840037870526938650,"bidder_id":2,"bid_ad_type":1,"creative_info":{"video":{"duration":30,"mimes":["video\/mp4"]}}}}}`)
+	ext := []byte(`{"prebid":{"targeting":{"hb_bidder_appnexus":"appnexus","hb_pb_appnexus":"20.00","hb_pb_cat_dur_appnex":"20.00_395_30s","hb_size":"1x1", "hb_uuid_appnexus":"837ea3b7-5598-4958-8c45-8e9ef2bf7cc1"},"type":"video","dealpriority":0,"dealtiersatisfied":false},"bidder":{"appnexus":{"brand_id":1,"auction_id":7840037870526938650,"bidder_id":2,"bid_ad_type":1,"creative_info":{"video":{"duration":30,"mimes":["video\/mp4"]}}}}}`)
 	return &openrtb.BidResponse{
 		SeatBid: []openrtb.SeatBid{{
 			Seat: "appnexus",
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 09d1af91..bd2fa114 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -695,6 +695,11 @@ func TestBidReturnsCreative(t *testing.T) {
 
 		assert.Equal(t, 0, len(resultingErrs), "%s. Test should not return errors \n", test.description)
 		assert.Equal(t, test.expectedCreativeMarkup, resultingBids[0].AdM, "%s. Ad markup string doesn't match expected \n", test.description)
+
+		var bidExt openrtb_ext.ExtBid
+		json.Unmarshal(resultingBids[0].Ext, &bidExt)
+		assert.Equal(t, 0, bidExt.Prebid.DealPriority, "%s. Test should have DealPriority set to 0", test.description)
+		assert.Equal(t, false, bidExt.Prebid.DealTierSatisfied, "%s. Test should have DealTierSatisfied set to false", test.description)
 	}
 }
 
@@ -1300,6 +1305,7 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 			Enforce: spec.EnforceLMT,
 		},
 		GDPR: config.GDPR{
+			Enabled:             spec.GDPREnabled,
 			UsersyncIfAmbiguous: !spec.AssumeGDPRApplies,
 			EEACountriesMap:     eeac,
 		},
@@ -1514,10 +1520,10 @@ func TestCategoryMapping(t *testing.T) {
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 40.0000, Cat: cats4, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1569,10 +1575,10 @@ func TestCategoryMappingNoIncludeBrandCategory(t *testing.T) {
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 40.0000, Cat: cats4, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1623,9 +1629,9 @@ func TestCategoryMappingTranslateCategoriesNil(t *testing.T) {
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 20.0000, Cat: cats2, W: 1, H: 1}
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1705,9 +1711,9 @@ func TestCategoryMappingTranslateCategoriesFalse(t *testing.T) {
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 20.0000, Cat: cats2, W: 1, H: 1}
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1757,11 +1763,11 @@ func TestCategoryDedupe(t *testing.T) {
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 20.0000, Cat: cats4, W: 1, H: 1}
 	bid5 := openrtb.Bid{ID: "bid_id5", ImpID: "imp_id5", Price: 20.0000, Cat: cats1, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	selectedBids := make(map[string]int)
 	expectedCategories := map[string]string{
@@ -1836,11 +1842,11 @@ func TestNoCategoryDedupe(t *testing.T) {
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 20.0000, Cat: cats4, W: 1, H: 1}
 	bid5 := openrtb.Bid{ID: "bid_id5", ImpID: "imp_id5", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	selectedBids := make(map[string]int)
 	expectedCategories := map[string]string{
@@ -1916,8 +1922,8 @@ func TestCategoryMappingBidderName(t *testing.T) {
 	bid1 := openrtb.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 10.0000, Cat: cats2, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids1 := []*pbsOrtbBid{
 		&bid1_1,
@@ -1970,8 +1976,8 @@ func TestCategoryMappingBidderNameNoCategories(t *testing.T) {
 	bid1 := openrtb.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 12.0000, Cat: cats2, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids1 := []*pbsOrtbBid{
 		&bid1_1,
@@ -2082,7 +2088,7 @@ func TestBidRejectionErrors(t *testing.T) {
 		innerBids := []*pbsOrtbBid{}
 		for _, bid := range test.bids {
 			currentBid := pbsOrtbBid{
-				bid, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: test.duration}, 0,
+				bid, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: test.duration}, 0, false,
 			}
 			innerBids = append(innerBids, &currentBid)
 		}
@@ -2131,8 +2137,8 @@ func TestCategoryMappingTwoBiddersOneBidEachNoCategorySamePrice(t *testing.T) {
 	bidApn1 := openrtb.Bid{ID: "bid_idApn1", ImpID: "imp_idApn1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 	bidApn2 := openrtb.Bid{ID: "bid_idApn2", ImpID: "imp_idApn2", Price: 10.0000, Cat: cats2, W: 1, H: 1}
 
-	bid1_Apn1 := pbsOrtbBid{&bidApn1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_Apn2 := pbsOrtbBid{&bidApn2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_Apn1 := pbsOrtbBid{&bidApn1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_Apn2 := pbsOrtbBid{&bidApn2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBidsApn1 := []*pbsOrtbBid{
 		&bid1_Apn1,
@@ -2193,12 +2199,13 @@ func TestUpdateRejections(t *testing.T) {
 
 func TestApplyDealSupport(t *testing.T) {
 	testCases := []struct {
-		description        string
-		dealPriority       int
-		impExt             json.RawMessage
-		targ               map[string]string
-		expectedHbPbCatDur string
-		expectedDealErr    string
+		description               string
+		dealPriority              int
+		impExt                    json.RawMessage
+		targ                      map[string]string
+		expectedHbPbCatDur        string
+		expectedDealErr           string
+		expectedDealTierSatisfied bool
 	}{
 		{
 			description:  "hb_pb_cat_dur should be modified",
@@ -2207,8 +2214,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_movies_30s",
 			},
-			expectedHbPbCatDur: "tier5_movies_30s",
-			expectedDealErr:    "",
+			expectedHbPbCatDur:        "tier5_movies_30s",
+			expectedDealErr:           "",
+			expectedDealTierSatisfied: true,
 		},
 		{
 			description:  "hb_pb_cat_dur should not be modified due to priority not exceeding min",
@@ -2217,8 +2225,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_medicine_30s",
 			},
-			expectedHbPbCatDur: "12.00_medicine_30s",
-			expectedDealErr:    "",
+			expectedHbPbCatDur:        "12.00_medicine_30s",
+			expectedDealErr:           "",
+			expectedDealTierSatisfied: false,
 		},
 		{
 			description:  "hb_pb_cat_dur should not be modified due to invalid config",
@@ -2227,8 +2236,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_games_30s",
 			},
-			expectedHbPbCatDur: "12.00_games_30s",
-			expectedDealErr:    "dealTier configuration invalid for bidder 'appnexus', imp ID 'imp_id1'",
+			expectedHbPbCatDur:        "12.00_games_30s",
+			expectedDealErr:           "dealTier configuration invalid for bidder 'appnexus', imp ID 'imp_id1'",
+			expectedDealTierSatisfied: false,
 		},
 		{
 			description:  "hb_pb_cat_dur should not be modified due to deal priority of 0",
@@ -2237,8 +2247,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_auto_30s",
 			},
-			expectedHbPbCatDur: "12.00_auto_30s",
-			expectedDealErr:    "",
+			expectedHbPbCatDur:        "12.00_auto_30s",
+			expectedDealErr:           "",
+			expectedDealTierSatisfied: false,
 		},
 	}
 
@@ -2254,7 +2265,7 @@ func TestApplyDealSupport(t *testing.T) {
 			},
 		}
 
-		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority, false}
 		bidCategory := map[string]string{
 			bid.bid.ID: test.targ["hb_pb_cat_dur"],
 		}
@@ -2270,6 +2281,7 @@ func TestApplyDealSupport(t *testing.T) {
 		dealErrs := applyDealSupport(bidRequest, auc, bidCategory)
 
 		assert.Equal(t, test.expectedHbPbCatDur, bidCategory[auc.winningBidsByBidder["imp_id1"][bidderName].bid.ID], test.description)
+		assert.Equal(t, test.expectedDealTierSatisfied, auc.winningBidsByBidder["imp_id1"][bidderName].dealTierSatisfied, "expectedDealTierSatisfied=%v when %v", test.expectedDealTierSatisfied, test.description)
 		if len(test.expectedDealErr) > 0 {
 			assert.Containsf(t, dealErrs, errors.New(test.expectedDealErr), "Expected error message not found in deal errors")
 		}
@@ -2368,11 +2380,12 @@ func TestValidateDealTier(t *testing.T) {
 
 func TestUpdateHbPbCatDur(t *testing.T) {
 	testCases := []struct {
-		description        string
-		targ               map[string]string
-		dealTier           openrtb_ext.DealTier
-		dealPriority       int
-		expectedHbPbCatDur string
+		description               string
+		targ                      map[string]string
+		dealTier                  openrtb_ext.DealTier
+		dealPriority              int
+		expectedHbPbCatDur        string
+		expectedDealTierSatisfied bool
 	}{
 		{
 			description: "hb_pb_cat_dur should be updated with prefix and tier",
@@ -2384,8 +2397,9 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 				Prefix:      "tier",
 				MinDealTier: 5,
 			},
-			dealPriority:       5,
-			expectedHbPbCatDur: "tier5_movies_30s",
+			dealPriority:              5,
+			expectedHbPbCatDur:        "tier5_movies_30s",
+			expectedDealTierSatisfied: true,
 		},
 		{
 			description: "hb_pb_cat_dur should not be updated due to bid priority",
@@ -2397,8 +2411,9 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 				Prefix:      "tier",
 				MinDealTier: 10,
 			},
-			dealPriority:       6,
-			expectedHbPbCatDur: "12.00_auto_30s",
+			dealPriority:              6,
+			expectedHbPbCatDur:        "12.00_auto_30s",
+			expectedDealTierSatisfied: false,
 		},
 		{
 			description: "hb_pb_cat_dur should be updated with prefix and tier",
@@ -2410,13 +2425,14 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 				Prefix:      "tier",
 				MinDealTier: 1,
 			},
-			dealPriority:       7,
-			expectedHbPbCatDur: "tier7_medicine_30s",
+			dealPriority:              7,
+			expectedHbPbCatDur:        "tier7_medicine_30s",
+			expectedDealTierSatisfied: true,
 		},
 	}
 
 	for _, test := range testCases {
-		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority, false}
 		bidCategory := map[string]string{
 			bid.bid.ID: test.targ["hb_pb_cat_dur"],
 		}
@@ -2424,10 +2440,12 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 		updateHbPbCatDur(&bid, test.dealTier, bidCategory)
 
 		assert.Equal(t, test.expectedHbPbCatDur, bidCategory[bid.bid.ID], test.description)
+		assert.Equal(t, test.expectedDealTierSatisfied, bid.dealTierSatisfied, test.description)
 	}
 }
 
 type exchangeSpec struct {
+	GDPREnabled       bool                   `json:"gdpr_enabled"`
 	IncomingRequest   exchangeRequest        `json:"incomingRequest"`
 	OutgoingRequests  map[string]*bidderSpec `json:"outgoingRequests"`
 	Response          exchangeResponse       `json:"response,omitempty"`
diff --git a/exchange/exchangetest/gdpr-geo-eu-off-device.json b/exchange/exchangetest/gdpr-geo-eu-off-device.json
index fc655de8..f704cdd5 100644
--- a/exchange/exchangetest/gdpr-geo-eu-off-device.json
+++ b/exchange/exchangetest/gdpr-geo-eu-off-device.json
@@ -1,5 +1,6 @@
 {
     "assume_gdpr_applies": false,
+    "gdpr_enabled": true,
     "incomingRequest": {
         "ortbRequest": {
             "id": "some-request-id",
diff --git a/exchange/exchangetest/gdpr-geo-eu-off.json b/exchange/exchangetest/gdpr-geo-eu-off.json
index 27a030f1..24357eb7 100644
--- a/exchange/exchangetest/gdpr-geo-eu-off.json
+++ b/exchange/exchangetest/gdpr-geo-eu-off.json
@@ -1,5 +1,6 @@
 {
     "assume_gdpr_applies": false,
+    "gdpr_enabled": true,
     "incomingRequest": {
         "ortbRequest": {
             "id": "some-request-id",
diff --git a/exchange/exchangetest/gdpr-geo-eu-on-featureflag-off.json b/exchange/exchangetest/gdpr-geo-eu-on-featureflag-off.json
new file mode 100644
index 00000000..6c6ca3ed
--- /dev/null
+++ b/exchange/exchangetest/gdpr-geo-eu-on-featureflag-off.json
@@ -0,0 +1,62 @@
+{
+    "assume_gdpr_applies": true,
+    "gdpr_enabled": false,
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }],
+            "user": {
+                "buyeruid": "some-buyer-id",
+                "geo": {
+                    "country": "FRA"
+                }
+            }
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }],
+                    "user": {
+                        "buyeruid": "some-buyer-id",
+                        "geo": {
+                            "country": "FRA"
+                        }
+                    }
+                },
+                "bidAdjustment": 1.0
+            },
+            "mockResponse": {
+                "errors": ["appnexus-error"]
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/gdpr-geo-eu-on.json b/exchange/exchangetest/gdpr-geo-eu-on.json
index 4ec42fc6..eb42a17c 100644
--- a/exchange/exchangetest/gdpr-geo-eu-on.json
+++ b/exchange/exchangetest/gdpr-geo-eu-on.json
@@ -1,5 +1,6 @@
 {
     "assume_gdpr_applies": true,
+    "gdpr_enabled": true,
     "incomingRequest": {
         "ortbRequest": {
             "id": "some-request-id",
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 94975e82..14293ae2 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -82,7 +82,7 @@ func TestCleanOpenRTBRequests(t *testing.T) {
 	}
 
 	for _, test := range testCases {
-		reqByBidders, _, _, err := cleanOpenRTBRequests(context.Background(), test.req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig)
+		reqByBidders, _, _, err := cleanOpenRTBRequests(context.Background(), test.req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig, &config.Account{})
 		if test.hasError {
 			assert.NotNil(t, err, "Error shouldn't be nil")
 		} else {
@@ -179,7 +179,7 @@ func TestCleanOpenRTBRequestsCCPA(t *testing.T) {
 			},
 		}
 
-		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig)
+		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig, &config.Account{})
 		result := results["appnexus"]
 
 		assert.Nil(t, errs)
@@ -229,7 +229,7 @@ func TestCleanOpenRTBRequestsCCPAErrors(t *testing.T) {
 				Enforce: true,
 			},
 		}
-		_, _, _, errs := cleanOpenRTBRequests(context.Background(), req, &reqExtStruct, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig)
+		_, _, _, errs := cleanOpenRTBRequests(context.Background(), req, &reqExtStruct, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig, &config.Account{})
 
 		assert.ElementsMatch(t, []error{test.expectError}, errs, test.description)
 	}
@@ -264,7 +264,7 @@ func TestCleanOpenRTBRequestsCOPPA(t *testing.T) {
 		req := newBidRequest(t)
 		req.Regs = &openrtb.Regs{COPPA: test.coppa}
 
-		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, config.Privacy{})
+		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, config.Privacy{}, &config.Account{})
 		result := results["appnexus"]
 
 		assert.Nil(t, errs)
@@ -366,7 +366,7 @@ func TestCleanOpenRTBRequestsSChain(t *testing.T) {
 			extRequest = unmarshaledExt
 		}
 
-		results, _, _, errs := cleanOpenRTBRequests(context.Background(), req, extRequest, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, config.Privacy{})
+		results, _, _, errs := cleanOpenRTBRequests(context.Background(), req, extRequest, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, config.Privacy{}, &config.Account{})
 		result := results["appnexus"]
 
 		if test.hasError == true {
@@ -943,7 +943,7 @@ func TestCleanOpenRTBRequestsLMT(t *testing.T) {
 			},
 		}
 
-		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig)
+		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: true}, true, privacyConfig, &config.Account{})
 		result := results["appnexus"]
 
 		assert.Nil(t, errs)
@@ -959,8 +959,12 @@ func TestCleanOpenRTBRequestsLMT(t *testing.T) {
 }
 
 func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
+	trueValue, falseValue := true, false
+
 	testCases := []struct {
 		description         string
+		gdprAccountEnabled  *bool
+		gdprHostEnabled     bool
 		gdpr                string
 		gdprConsent         string
 		gdprScrub           bool
@@ -968,40 +972,96 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 		expectPrivacyLabels pbsmetrics.PrivacyLabels
 	}{
 		{
-			description: "Enforce - TCF Invalid",
-			gdpr:        "1",
-			gdprConsent: "malformed",
-			gdprScrub:   false,
+			description:        "Enforce - TCF Invalid",
+			gdprAccountEnabled: &trueValue,
+			gdprHostEnabled:    true,
+			gdpr:               "1",
+			gdprConsent:        "malformed",
+			gdprScrub:          false,
 			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: "",
 			},
 		},
 		{
-			description: "Enforce - TCF 1",
-			gdpr:        "1",
-			gdprConsent: "BONV8oqONXwgmADACHENAO7pqzAAppY",
-			gdprScrub:   true,
+			description:        "Enforce - TCF 1",
+			gdprAccountEnabled: &trueValue,
+			gdprHostEnabled:    true,
+			gdpr:               "1",
+			gdprConsent:        "BONV8oqONXwgmADACHENAO7pqzAAppY",
+			gdprScrub:          true,
 			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: pbsmetrics.TCFVersionV1,
 			},
 		},
 		{
-			description: "Enforce - TCF 2",
-			gdpr:        "1",
-			gdprConsent: "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
-			gdprScrub:   true,
+			description:        "Enforce - TCF 2",
+			gdprAccountEnabled: &trueValue,
+			gdprHostEnabled:    true,
+			gdpr:               "1",
+			gdprConsent:        "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
+			gdprScrub:          true,
 			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: pbsmetrics.TCFVersionV2,
 			},
 		},
 		{
-			description: "Not Enforce - TCF 1",
-			gdpr:        "0",
-			gdprConsent: "BONV8oqONXwgmADACHENAO7pqzAAppY",
-			gdprScrub:   false,
+			description:        "Not Enforce - TCF 1",
+			gdprAccountEnabled: &trueValue,
+			gdprHostEnabled:    true,
+			gdpr:               "0",
+			gdprConsent:        "BONV8oqONXwgmADACHENAO7pqzAAppY",
+			gdprScrub:          false,
+			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
+				GDPREnforced:   false,
+				GDPRTCFVersion: "",
+			},
+		},
+		{
+			description:        "Enforce - TCF 1; account GDPR enabled, host GDPR setting disregarded",
+			gdprAccountEnabled: &trueValue,
+			gdprHostEnabled:    false,
+			gdpr:               "1",
+			gdprConsent:        "BONV8oqONXwgmADACHENAO7pqzAAppY",
+			gdprScrub:          true,
+			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
+				GDPREnforced:   true,
+				GDPRTCFVersion: pbsmetrics.TCFVersionV1,
+			},
+		},
+		{
+			description:        "Not Enforce - TCF 1; account GDPR disabled, host GDPR setting disregarded",
+			gdprAccountEnabled: &falseValue,
+			gdprHostEnabled:    true,
+			gdpr:               "1",
+			gdprConsent:        "BONV8oqONXwgmADACHENAO7pqzAAppY",
+			gdprScrub:          false,
+			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
+				GDPREnforced:   false,
+				GDPRTCFVersion: "",
+			},
+		},
+		{
+			description:        "Enforce - TCF 1; account GDPR not specified, host GDPR enabled",
+			gdprAccountEnabled: nil,
+			gdprHostEnabled:    true,
+			gdpr:               "1",
+			gdprConsent:        "BONV8oqONXwgmADACHENAO7pqzAAppY",
+			gdprScrub:          true,
+			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
+				GDPREnforced:   true,
+				GDPRTCFVersion: pbsmetrics.TCFVersionV1,
+			},
+		},
+		{
+			description:        "Not Enforce - TCF 1; account GDPR not specified, host GDPR disabled",
+			gdprAccountEnabled: nil,
+			gdprHostEnabled:    false,
+			gdpr:               "1",
+			gdprConsent:        "BONV8oqONXwgmADACHENAO7pqzAAppY",
+			gdprScrub:          false,
 			expectPrivacyLabels: pbsmetrics.PrivacyLabels{
 				GDPREnforced:   false,
 				GDPRTCFVersion: "",
@@ -1018,13 +1078,30 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 
 		privacyConfig := config.Privacy{
 			GDPR: config.GDPR{
+				Enabled: test.gdprHostEnabled,
 				TCF2: config.TCF2{
 					Enabled: true,
 				},
 			},
 		}
 
-		results, _, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), req, nil, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{personalInfoAllowed: !test.gdprScrub}, true, privacyConfig)
+		accountConfig := config.Account{
+			GDPR: config.AccountGDPR{
+				Enabled: test.gdprAccountEnabled,
+			},
+		}
+
+		results, _, privacyLabels, errs := cleanOpenRTBRequests(
+			context.Background(),
+			req,
+			nil,
+			&emptyUsersync{},
+			map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{},
+			pbsmetrics.Labels{},
+			&permissionsMock{personalInfoAllowed: !test.gdprScrub},
+			true,
+			privacyConfig,
+			&accountConfig)
 		result := results["appnexus"]
 
 		assert.Nil(t, errs)
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index 15e6ba19..a6e74966 100755
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -27,6 +27,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderAdtelligent):      syncConfig,
 			string(openrtb_ext.BidderAdvangelists):     syncConfig,
 			string(openrtb_ext.BidderAJA):              syncConfig,
+			string(openrtb_ext.BidderAMX):              syncConfig,
 			string(openrtb_ext.BidderAppnexus):         syncConfig,
 			string(openrtb_ext.BidderAvocet):           syncConfig,
 			string(openrtb_ext.BidderBeachfront):       syncConfig,
@@ -59,6 +60,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderMgid):             syncConfig,
 			string(openrtb_ext.BidderNanoInteractive):  syncConfig,
 			string(openrtb_ext.BidderNinthDecimal):     syncConfig,
+			string(openrtb_ext.BidderNoBid):            syncConfig,
 			string(openrtb_ext.BidderOpenx):            syncConfig,
 			string(openrtb_ext.BidderPubmatic):         syncConfig,
 			string(openrtb_ext.BidderPulsepoint):       syncConfig,
@@ -100,6 +102,7 @@ func TestNewSyncerMap(t *testing.T) {
 		openrtb_ext.BidderMobileFuse:   true,
 		openrtb_ext.BidderOrbidder:     true,
 		openrtb_ext.BidderPubnative:    true,
+		openrtb_ext.BidderSilverMob:    true,
 		openrtb_ext.BidderSmaato:       true,
 		openrtb_ext.BidderTappx:        true,
 		openrtb_ext.BidderYeahmobi:     true,