Repository: prebid/prebid-server
Pull request #1737 (2021-03-05 14:54:56)

beachfront: Changes to support real 204
An optional parameter has been added to beachfront's banner endpoint to support returning a 204 response instead of an empty array on no content. These changes support that.


Patch:
diff --git a/adapters/33across/usersync.go b/adapters/33across/usersync.go
index 7bc9ae45..df26f3b6 100644
--- a/adapters/33across/usersync.go
+++ b/adapters/33across/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func New33AcrossSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("33across", 58, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("33across", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/acuityads/usersync.go b/adapters/acuityads/usersync.go
index 7eedf78d..e2fc1f41 100644
--- a/adapters/acuityads/usersync.go
+++ b/adapters/acuityads/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAcuityAdsSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("acuityads", 231, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("acuityads", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adform/usersync.go b/adapters/adform/usersync.go
index 32b4e3a9..6a237f79 100644
--- a/adapters/adform/usersync.go
+++ b/adapters/adform/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAdformSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adform", 50, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adform", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adkernel/usersync.go b/adapters/adkernel/usersync.go
index 2e2ebdb9..2de82a00 100644
--- a/adapters/adkernel/usersync.go
+++ b/adapters/adkernel/usersync.go
@@ -7,8 +7,6 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const adkernelGDPRVendorID = uint16(14)
-
 func NewAdkernelSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adkernel", 14, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adkernel", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adkernelAdn/usersync.go b/adapters/adkernelAdn/usersync.go
index 0bedac38..5a890e15 100644
--- a/adapters/adkernelAdn/usersync.go
+++ b/adapters/adkernelAdn/usersync.go
@@ -7,8 +7,6 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const adkernelGDPRVendorID = uint16(14)
-
 func NewAdkernelAdnSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adkernelAdn", 14, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adkernelAdn", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adman/usersync.go b/adapters/adman/usersync.go
index aae6afcd..2cb62fe7 100644
--- a/adapters/adman/usersync.go
+++ b/adapters/adman/usersync.go
@@ -9,5 +9,5 @@ import (
 
 // NewAdmanSyncer returns adman syncer
 func NewAdmanSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adman", 149, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adman", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/admixer/usersync.go b/adapters/admixer/usersync.go
index 0a7f50ab..89e162df 100644
--- a/adapters/admixer/usersync.go
+++ b/adapters/admixer/usersync.go
@@ -1,11 +1,12 @@
 package admixer
 
 import (
+	"text/template"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/usersync"
-	"text/template"
 )
 
 func NewAdmixerSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("admixer", 511, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("admixer", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adocean/usersync.go b/adapters/adocean/usersync.go
index 650e517a..b189f822 100644
--- a/adapters/adocean/usersync.go
+++ b/adapters/adocean/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAdOceanSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adocean", 328, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adocean", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adpone/usersync.go b/adapters/adpone/usersync.go
index 67d4c998..38dec19b 100644
--- a/adapters/adpone/usersync.go
+++ b/adapters/adpone/usersync.go
@@ -7,13 +7,11 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const adponeGDPRVendorID = uint16(799)
 const adponeFamilyName = "adpone"
 
 func NewadponeSyncer(urlTemplate *template.Template) usersync.Usersyncer {
 	return adapters.NewSyncer(
 		adponeFamilyName,
-		adponeGDPRVendorID,
 		urlTemplate,
 		adapters.SyncTypeRedirect,
 	)
diff --git a/adapters/adtarget/usersync.go b/adapters/adtarget/usersync.go
index 20bced25..d720f110 100644
--- a/adapters/adtarget/usersync.go
+++ b/adapters/adtarget/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAdtargetSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adtarget", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adtarget", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/adtelligent/usersync.go b/adapters/adtelligent/usersync.go
index 087b5bdd..613c8e29 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", 410, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adtelligent", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/advangelists/usersync.go b/adapters/advangelists/usersync.go
index 10c46d18..83930774 100644
--- a/adapters/advangelists/usersync.go
+++ b/adapters/advangelists/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAdvangelistsSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("advangelists", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("advangelists", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/adyoulike/adyoulike.go b/adapters/adyoulike/adyoulike.go
new file mode 100644
index 00000000..9a137a41
--- /dev/null
+++ b/adapters/adyoulike/adyoulike.go
@@ -0,0 +1,137 @@
+package adyoulike
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"net/http"
+
+	"github.com/buger/jsonparser"
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+)
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	return &adapter{
+		endpoint: config.Endpoint,
+	}, nil
+}
+
+type adapter struct {
+	endpoint string
+}
+
+func (a *adapter) MakeRequests(
+	openRTBRequest *openrtb.BidRequest,
+	reqInfo *adapters.ExtraRequestInfo,
+) (
+	requestsToBidder []*adapters.RequestData,
+	errs []error,
+) {
+	var err error
+	var tagID string
+
+	reqCopy := *openRTBRequest
+	reqCopy.Imp = []openrtb.Imp{}
+	for ind, imp := range openRTBRequest.Imp {
+		reqCopy.Imp = append(reqCopy.Imp, imp)
+
+		tagID, err = jsonparser.GetString(reqCopy.Imp[ind].Ext, "bidder", "placement")
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		reqCopy.Imp[ind].TagID = tagID
+	}
+
+	openRTBRequestJSON, err := json.Marshal(reqCopy)
+	if err != nil {
+		errs = append(errs, err)
+	}
+
+	if len(errs) > 0 {
+		return nil, errs
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("x-openrtb-version", "2.5")
+
+	requestToBidder := &adapters.RequestData{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    openRTBRequestJSON,
+		Headers: headers,
+	}
+	requestsToBidder = append(requestsToBidder, requestToBidder)
+
+	return requestsToBidder, errs
+}
+
+const unexpectedStatusCodeFormat = "" +
+	"Unexpected status code: %d. Run with request.debug = 1 for more info"
+
+func (a *adapter) MakeBids(
+	openRTBRequest *openrtb.BidRequest,
+	requestToBidder *adapters.RequestData,
+	bidderRawResponse *adapters.ResponseData,
+) (
+	bidderResponse *adapters.BidderResponse,
+	errs []error,
+) {
+	switch bidderRawResponse.StatusCode {
+	case http.StatusOK:
+		break
+	case http.StatusNoContent:
+		return nil, []error{errors.New("MakeBids error: No Content")}
+	case http.StatusBadRequest:
+		err := &errortypes.BadInput{
+			Message: fmt.Sprintf(unexpectedStatusCodeFormat, bidderRawResponse.StatusCode),
+		}
+		return nil, []error{err}
+	default:
+		err := &errortypes.BadServerResponse{
+			Message: fmt.Sprintf(unexpectedStatusCodeFormat, bidderRawResponse.StatusCode),
+		}
+		return nil, []error{err}
+	}
+
+	var openRTBBidderResponse openrtb.BidResponse
+	if err := json.Unmarshal(bidderRawResponse.Body, &openRTBBidderResponse); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(openRTBRequest.Imp))
+	bidResponse.Currency = openRTBBidderResponse.Cur
+	for _, seatBid := range openRTBBidderResponse.SeatBid {
+		for idx := range seatBid.Bid {
+			b := &adapters.TypedBid{
+				Bid:     &seatBid.Bid[idx],
+				BidType: getMediaTypeForImp(seatBid.Bid[idx].ImpID, openRTBRequest.Imp),
+			}
+			bidResponse.Bids = append(bidResponse.Bids, b)
+		}
+	}
+	return bidResponse, nil
+}
+
+// getMediaTypeForBid determines which type of bid.
+func getMediaTypeForImp(impID string, imps []openrtb.Imp) openrtb_ext.BidType {
+	mediaType := openrtb_ext.BidTypeBanner
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner == nil && imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			} else if imp.Banner == nil && imp.Native != nil {
+				mediaType = openrtb_ext.BidTypeNative
+			}
+		}
+	}
+
+	return mediaType
+}
diff --git a/adapters/adyoulike/usersync.go b/adapters/adyoulike/usersync.go
new file mode 100644
index 00000000..ffea6f69
--- /dev/null
+++ b/adapters/adyoulike/usersync.go
@@ -0,0 +1,12 @@
+package adyoulike
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewAdyoulikeSyncer(urlTemplate *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("adyoulike", urlTemplate, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/aja/usersync.go b/adapters/aja/usersync.go
index c54405db..6a9fad74 100644
--- a/adapters/aja/usersync.go
+++ b/adapters/aja/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAJASyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("aja", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("aja", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/amx/usersync.go b/adapters/amx/usersync.go
index 28e6ac0e..17ad04d5 100644
--- a/adapters/amx/usersync.go
+++ b/adapters/amx/usersync.go
@@ -9,5 +9,5 @@ import (
 
 // NewAMXSyncer produces an AMX RTB usersyncer
 func NewAMXSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("amx", 737, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("amx", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/appnexus/usersync.go b/adapters/appnexus/usersync.go
index 22f46f1e..d29f0e3c 100644
--- a/adapters/appnexus/usersync.go
+++ b/adapters/appnexus/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAppnexusSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("adnxs", 32, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("adnxs", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/audienceNetwork/usersync.go b/adapters/audienceNetwork/usersync.go
index 45c1281d..4dd0b68c 100644
--- a/adapters/audienceNetwork/usersync.go
+++ b/adapters/audienceNetwork/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewFacebookSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("audienceNetwork", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("audienceNetwork", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/avocet/usersync.go b/adapters/avocet/usersync.go
index f1075ab3..0cfa055a 100644
--- a/adapters/avocet/usersync.go
+++ b/adapters/avocet/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewAvocetSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("avocet", 63, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("avocet", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/beachfront/beachfront.go b/adapters/beachfront/beachfront.go
index 3a431c9c..58554577 100644
--- a/adapters/beachfront/beachfront.go
+++ b/adapters/beachfront/beachfront.go
@@ -76,6 +76,7 @@ type beachfrontBannerRequest struct {
 	AdapterVersion string           `json:"adapterVersion"`
 	IP             string           `json:"ip"`
 	RequestID      string           `json:"requestId"`
+	Real204        bool             `json:"real204"`
 }
 
 type beachfrontSlot struct {
@@ -367,6 +368,7 @@ func getBannerRequest(request *openrtb.BidRequest) (beachfrontBannerRequest, []e
 	if request.Imp[0].Secure != nil {
 		bfr.Secure = *request.Imp[0].Secure
 	}
+	bfr.Real204 = true
 
 	return bfr, errs
 }
@@ -465,7 +467,7 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
 		}
 
 		bfReqs[i].Request.Imp = nil
-		bfReqs[i].Request.Imp = make([]openrtb.Imp, 1, 1)
+		bfReqs[i].Request.Imp = make([]openrtb.Imp, 1)
 		bfReqs[i].Request.Imp[0] = imp
 
 	}
@@ -481,18 +483,12 @@ func getVideoRequests(request *openrtb.BidRequest) ([]beachfrontVideoRequest, []
 }
 
 func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
-	var bids []openrtb.Bid
-
-	// The case of response status == 200 and response body length == 2 below covers the case of the banner endpoint returning
-	// an empty JSON array ('[]'), which is functionally no content.
-	if response.StatusCode == http.StatusNoContent || (response.StatusCode == http.StatusOK && len(response.Body) <= 2) {
-		return nil, []error{&errortypes.BadInput{
-			Message: fmt.Sprintf("no content or truncated content received from server. status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri),
-		}}
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
 	}
 
 	if response.StatusCode >= http.StatusInternalServerError {
-		return nil, []error{&errortypes.BadInput{
+		return nil, []error{&errortypes.BadServerResponse{
 			Message: fmt.Sprintf("server error status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri),
 		}}
 	}
@@ -507,8 +503,9 @@ func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, extern
 		return nil, []error{fmt.Errorf("unexpected status code %d from %s. Run with request.debug = 1 for more info", response.StatusCode, externalRequest.Uri)}
 	}
 
-	var xtrnal openrtb.BidRequest
+	var bids []openrtb.Bid
 	var errs = make([]error, 0)
+	var xtrnal openrtb.BidRequest
 
 	// For video, which uses RTB for the external request, this will unmarshal as expected. For banner, it will
 	// only get the User struct and everything else will be nil
@@ -524,6 +521,7 @@ func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, extern
 
 	var dur beachfrontVideoBidExtension
 	bidResponse := adapters.NewBidderResponseWithBidsCapacity(BidCapacity)
+
 	for i := 0; i < len(bids); i++ {
 
 		// If we unmarshal without an error, this is an AdM video
diff --git a/adapters/beachfront/usersync.go b/adapters/beachfront/usersync.go
index a6502331..72466b59 100644
--- a/adapters/beachfront/usersync.go
+++ b/adapters/beachfront/usersync.go
@@ -7,12 +7,9 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-var VENDOR_ID uint16 = 335
-
 func NewBeachfrontSyncer(temp *template.Template) usersync.Usersyncer {
 	return adapters.NewSyncer(
 		"beachfront",
-		VENDOR_ID,
 		temp,
 		adapters.SyncTypeIframe)
 }
diff --git a/adapters/beintoo/usersync.go b/adapters/beintoo/usersync.go
index a225a2b1..fb60c6ab 100644
--- a/adapters/beintoo/usersync.go
+++ b/adapters/beintoo/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewBeintooSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("Beintoo", 618, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("Beintoo", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/between/usersync.go b/adapters/between/usersync.go
index a34521fe..14228273 100644
--- a/adapters/between/usersync.go
+++ b/adapters/between/usersync.go
@@ -9,5 +9,5 @@ import (
 
 // NewBetweenSyncer returns "between" syncer
 func NewBetweenSyncer(template *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("between", 724, template, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("between", template, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/brightroll/usersync.go b/adapters/brightroll/usersync.go
index b33cc5a2..099303fd 100644
--- a/adapters/brightroll/usersync.go
+++ b/adapters/brightroll/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewBrightrollSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("brightroll", 25, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("brightroll", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/colossus/usersync.go b/adapters/colossus/usersync.go
index a4e82ee3..bb25b187 100644
--- a/adapters/colossus/usersync.go
+++ b/adapters/colossus/usersync.go
@@ -9,5 +9,5 @@ import (
 
 // NewColossusSyncer returns colossus syncer
 func NewColossusSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("colossus", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("colossus", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/connectad/usersync.go b/adapters/connectad/usersync.go
index 5661cb5d..bae96656 100644
--- a/adapters/connectad/usersync.go
+++ b/adapters/connectad/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewConnectAdSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("connectad", 138, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("connectad", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/consumable/usersync.go b/adapters/consumable/usersync.go
index 0e0938c7..0cb25ca9 100644
--- a/adapters/consumable/usersync.go
+++ b/adapters/consumable/usersync.go
@@ -7,13 +7,9 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-var VENDOR_ID uint16 = 591
-
 func NewConsumableSyncer(temp *template.Template) usersync.Usersyncer {
-
 	return adapters.NewSyncer(
 		"consumable",
-		VENDOR_ID,
 		temp,
 		adapters.SyncTypeRedirect)
 }
diff --git a/adapters/conversant/usersync.go b/adapters/conversant/usersync.go
index c2676df6..a38631f2 100644
--- a/adapters/conversant/usersync.go
+++ b/adapters/conversant/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewConversantSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("conversant", 24, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("conversant", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/cpmstar/usersync.go b/adapters/cpmstar/usersync.go
index 9c864e24..d3086f65 100644
--- a/adapters/cpmstar/usersync.go
+++ b/adapters/cpmstar/usersync.go
@@ -9,5 +9,5 @@ import (
 
 //NewCpmstarSyncer :
 func NewCpmstarSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("cpmstar", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("cpmstar", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/datablocks/usersync.go b/adapters/datablocks/usersync.go
index 2b47b259..2c69963a 100644
--- a/adapters/datablocks/usersync.go
+++ b/adapters/datablocks/usersync.go
@@ -7,8 +7,6 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const datablocksGDPRVendorID = uint16(0)
-
 func NewDatablocksSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("datablocks", datablocksGDPRVendorID, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("datablocks", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/deepintent/usersync.go b/adapters/deepintent/usersync.go
index 9e803df6..7a17f533 100644
--- a/adapters/deepintent/usersync.go
+++ b/adapters/deepintent/usersync.go
@@ -9,5 +9,5 @@ import (
 
 // NewDeepintentSyncer returns deepintent syncer
 func NewDeepintentSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("deepintent", 541, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("deepintent", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/dmx/usersync.go b/adapters/dmx/usersync.go
index 98e56234..07fedf1c 100644
--- a/adapters/dmx/usersync.go
+++ b/adapters/dmx/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewDmxSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("dmx", 144, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("dmx", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/emx_digital/usersync.go b/adapters/emx_digital/usersync.go
index a453955b..2d3011e0 100644
--- a/adapters/emx_digital/usersync.go
+++ b/adapters/emx_digital/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewEMXDigitalSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("emx_digital", 183, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("emx_digital", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/engagebdr/usersync.go b/adapters/engagebdr/usersync.go
index ae4047aa..205097b0 100644
--- a/adapters/engagebdr/usersync.go
+++ b/adapters/engagebdr/usersync.go
@@ -1,11 +1,12 @@
 package engagebdr
 
 import (
+	"text/template"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/usersync"
-	"text/template"
 )
 
 func NewEngageBDRSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("engagebdr", 62, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("engagebdr", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/eplanning/usersync.go b/adapters/eplanning/usersync.go
index faa7fa82..6e8abf5d 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", 90, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("eplanning", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/gamma/usersync.go b/adapters/gamma/usersync.go
index f19c522c..4e4412a1 100644
--- a/adapters/gamma/usersync.go
+++ b/adapters/gamma/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewGammaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("gamma", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("gamma", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/gamoshi/usersync.go b/adapters/gamoshi/usersync.go
index 6b7c43dd..9d6cdd0e 100644
--- a/adapters/gamoshi/usersync.go
+++ b/adapters/gamoshi/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewGamoshiSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("gamoshi", 644, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("gamoshi", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/grid/usersync.go b/adapters/grid/usersync.go
index afdc5db7..31788ea3 100644
--- a/adapters/grid/usersync.go
+++ b/adapters/grid/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewGridSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("grid", 686, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("grid", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/gumgum/usersync.go b/adapters/gumgum/usersync.go
index 5d29c7dc..defef87d 100644
--- a/adapters/gumgum/usersync.go
+++ b/adapters/gumgum/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewGumGumSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("gumgum", 61, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("gumgum", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/improvedigital/improvedigital.go b/adapters/improvedigital/improvedigital.go
index 0d5c043e..b1cc3640 100644
--- a/adapters/improvedigital/improvedigital.go
+++ b/adapters/improvedigital/improvedigital.go
@@ -114,6 +114,10 @@ func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType,
 				return openrtb_ext.BidTypeVideo, nil
 			}
 
+			if imp.Native != nil {
+				return openrtb_ext.BidTypeNative, nil
+			}
+
 			return "", &errortypes.BadServerResponse{
 				Message: fmt.Sprintf("Unknown impression type for ID: \"%s\"", impID),
 			}
diff --git a/adapters/improvedigital/usersync.go b/adapters/improvedigital/usersync.go
index 72c3ddaf..a58b97c3 100644
--- a/adapters/improvedigital/usersync.go
+++ b/adapters/improvedigital/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewImprovedigitalSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("improvedigital", 253, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("improvedigital", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/invibes/usersync.go b/adapters/invibes/usersync.go
index 468e604c..e6922444 100644
--- a/adapters/invibes/usersync.go
+++ b/adapters/invibes/usersync.go
@@ -10,7 +10,6 @@ import (
 func NewInvibesSyncer(urlTemplate *template.Template) usersync.Usersyncer {
 	return adapters.NewSyncer(
 		"invibes",
-		436,
 		urlTemplate,
 		adapters.SyncTypeIframe,
 	)
diff --git a/adapters/ix/usersync.go b/adapters/ix/usersync.go
index 6f355894..621fa179 100644
--- a/adapters/ix/usersync.go
+++ b/adapters/ix/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewIxSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("ix", 10, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("ix", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/jixie/usersync.go b/adapters/jixie/usersync.go
index 8c1d5c07..137d78f2 100644
--- a/adapters/jixie/usersync.go
+++ b/adapters/jixie/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewJixieSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("jixie", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("jixie", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/krushmedia/usersync.go b/adapters/krushmedia/usersync.go
index 5dc1471f..860cb220 100644
--- a/adapters/krushmedia/usersync.go
+++ b/adapters/krushmedia/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewKrushmediaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("krushmedia", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("krushmedia", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/lifestreet/usersync.go b/adapters/lifestreet/usersync.go
index 15ffde4d..f5300eba 100644
--- a/adapters/lifestreet/usersync.go
+++ b/adapters/lifestreet/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewLifestreetSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("lifestreet", 67, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("lifestreet", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/lockerdome/usersync.go b/adapters/lockerdome/usersync.go
index fb01f8e2..d5cce168 100644
--- a/adapters/lockerdome/usersync.go
+++ b/adapters/lockerdome/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewLockerDomeSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("lockerdome", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("lockerdome", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/logicad/usersync.go b/adapters/logicad/usersync.go
index d26a197b..e685cc98 100644
--- a/adapters/logicad/usersync.go
+++ b/adapters/logicad/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewLogicadSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("logicad", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("logicad", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/lunamedia/usersync.go b/adapters/lunamedia/usersync.go
index 7ad54e38..39c9a808 100644
--- a/adapters/lunamedia/usersync.go
+++ b/adapters/lunamedia/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewLunaMediaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("lunamedia", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("lunamedia", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/marsmedia/usersync.go b/adapters/marsmedia/usersync.go
index 50996f32..4ac76d1f 100644
--- a/adapters/marsmedia/usersync.go
+++ b/adapters/marsmedia/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewMarsmediaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("marsmedia", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("marsmedia", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/mediafuse/usersync.go b/adapters/mediafuse/usersync.go
index 5381bf36..b91a6b50 100644
--- a/adapters/mediafuse/usersync.go
+++ b/adapters/mediafuse/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewMediafuseSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("mediafuse", 411, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("mediafuse", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/mgid/usersync.go b/adapters/mgid/usersync.go
index fbdb95f0..94cf12e1 100644
--- a/adapters/mgid/usersync.go
+++ b/adapters/mgid/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewMgidSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("mgid", 358, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("mgid", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/nanointeractive/usersync.go b/adapters/nanointeractive/usersync.go
index e6227436..6bd9cd1f 100644
--- a/adapters/nanointeractive/usersync.go
+++ b/adapters/nanointeractive/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewNanoInteractiveSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("nanointeractive", 72, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("nanointeractive", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/ninthdecimal/usersync.go b/adapters/ninthdecimal/usersync.go
index 7a8d029c..a01fdb63 100755
--- a/adapters/ninthdecimal/usersync.go
+++ b/adapters/ninthdecimal/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewNinthDecimalSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("ninthdecimal", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("ninthdecimal", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/nobid/usersync.go b/adapters/nobid/usersync.go
index c21413f5..44207564 100644
--- a/adapters/nobid/usersync.go
+++ b/adapters/nobid/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewNoBidSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("nobid", 816, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("nobid", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/onetag/usersync.go b/adapters/onetag/usersync.go
index f36b82a8..9a2b700d 100644
--- a/adapters/onetag/usersync.go
+++ b/adapters/onetag/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSyncer(template *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("onetag", 241, template, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("onetag", template, adapters.SyncTypeIframe)
 }
diff --git a/adapters/openx/usersync.go b/adapters/openx/usersync.go
index bb4b328c..875b60fb 100644
--- a/adapters/openx/usersync.go
+++ b/adapters/openx/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewOpenxSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("openx", 69, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("openx", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/pubmatic/usersync.go b/adapters/pubmatic/usersync.go
index 7b4d8e86..822f13ce 100644
--- a/adapters/pubmatic/usersync.go
+++ b/adapters/pubmatic/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewPubmaticSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("pubmatic", 76, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("pubmatic", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/pulsepoint/usersync.go b/adapters/pulsepoint/usersync.go
index 58de835b..1b6903f9 100644
--- a/adapters/pulsepoint/usersync.go
+++ b/adapters/pulsepoint/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewPulsepointSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("pulsepoint", 81, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("pulsepoint", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/rhythmone/rhythmone.go b/adapters/rhythmone/rhythmone.go
index 7dd94a49..a507e778 100644
--- a/adapters/rhythmone/rhythmone.go
+++ b/adapters/rhythmone/rhythmone.go
@@ -132,9 +132,9 @@ func (a *RhythmoneAdapter) preProcess(req *openrtb.BidRequest, errors []error) (
 			errors = append(errors, err)
 			return nil, "", errors
 		}
-		bidderExtCopy := openrtb_ext.ExtBid{
-			Bidder: rhythmoneExtCopy,
-		}
+		bidderExtCopy := struct {
+			Bidder json.RawMessage `json:"bidder,omitempty"`
+		}{rhythmoneExtCopy}
 		impExtCopy, err := json.Marshal(&bidderExtCopy)
 		if err != nil {
 			errors = append(errors, err)
diff --git a/adapters/rhythmone/usersync.go b/adapters/rhythmone/usersync.go
index 0f7db388..990fcb06 100644
--- a/adapters/rhythmone/usersync.go
+++ b/adapters/rhythmone/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewRhythmoneSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("rhythmone", 36, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("rhythmone", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/rtbhouse/usersync.go b/adapters/rtbhouse/usersync.go
index 3e38d67e..baa0b994 100644
--- a/adapters/rtbhouse/usersync.go
+++ b/adapters/rtbhouse/usersync.go
@@ -7,13 +7,11 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-const rtbHouseGDPRVendorID = uint16(16)
 const rtbHouseFamilyName = "rtbhouse"
 
 func NewRTBHouseSyncer(urlTemplate *template.Template) usersync.Usersyncer {
 	return adapters.NewSyncer(
 		rtbHouseFamilyName,
-		rtbHouseGDPRVendorID,
 		urlTemplate,
 		adapters.SyncTypeRedirect,
 	)
diff --git a/adapters/rubicon/usersync.go b/adapters/rubicon/usersync.go
index 08d98825..a4ab464a 100644
--- a/adapters/rubicon/usersync.go
+++ b/adapters/rubicon/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewRubiconSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("rubicon", 52, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("rubicon", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/sharethrough/usersync.go b/adapters/sharethrough/usersync.go
index a951fcd6..f76f41ca 100644
--- a/adapters/sharethrough/usersync.go
+++ b/adapters/sharethrough/usersync.go
@@ -1,11 +1,12 @@
 package sharethrough
 
 import (
+	"text/template"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/usersync"
-	"text/template"
 )
 
 func NewSharethroughSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("sharethrough", 80, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("sharethrough", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/smartadserver/usersync.go b/adapters/smartadserver/usersync.go
index 95b305ff..f7199965 100644
--- a/adapters/smartadserver/usersync.go
+++ b/adapters/smartadserver/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSmartadserverSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("smartadserver", 45, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("smartadserver", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/smartrtb/usersync.go b/adapters/smartrtb/usersync.go
index 2f7b1dc3..74ef0e99 100644
--- a/adapters/smartrtb/usersync.go
+++ b/adapters/smartrtb/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSmartRTBSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("smartrtb", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("smartrtb", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/smartyads/usersync.go b/adapters/smartyads/usersync.go
index 839621e9..9075aa9b 100644
--- a/adapters/smartyads/usersync.go
+++ b/adapters/smartyads/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSmartyAdsSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("smartyads", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("smartyads", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/somoaudience/usersync.go b/adapters/somoaudience/usersync.go
index e1e7e2ef..5d1ddd71 100644
--- a/adapters/somoaudience/usersync.go
+++ b/adapters/somoaudience/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSomoaudienceSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("somoaudience", 341, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("somoaudience", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/sonobi/usersync.go b/adapters/sonobi/usersync.go
index 6986d0fd..6fedd8bf 100644
--- a/adapters/sonobi/usersync.go
+++ b/adapters/sonobi/usersync.go
@@ -1,11 +1,12 @@
 package sonobi
 
 import (
+	"text/template"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/usersync"
-	"text/template"
 )
 
 func NewSonobiSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("sonobi", 104, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("sonobi", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/sovrn/usersync.go b/adapters/sovrn/usersync.go
index b4de6237..225f2888 100644
--- a/adapters/sovrn/usersync.go
+++ b/adapters/sovrn/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSovrnSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("sovrn", 13, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("sovrn", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/synacormedia/usersync.go b/adapters/synacormedia/usersync.go
index 988c1b9e..c7fa5c42 100644
--- a/adapters/synacormedia/usersync.go
+++ b/adapters/synacormedia/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewSynacorMediaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("synacormedia", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("synacormedia", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/syncer.go b/adapters/syncer.go
index 122bcc7e..b9752b50 100644
--- a/adapters/syncer.go
+++ b/adapters/syncer.go
@@ -4,34 +4,21 @@ import (
 	"text/template"
 
 	"github.com/prebid/prebid-server/macros"
-	"github.com/prebid/prebid-server/openrtb_ext"
 	"github.com/prebid/prebid-server/privacy"
 	"github.com/prebid/prebid-server/usersync"
 )
 
-func GDPRAwareSyncerIDs(syncers map[openrtb_ext.BidderName]usersync.Usersyncer) map[openrtb_ext.BidderName]uint16 {
-	gdprAwareSyncers := make(map[openrtb_ext.BidderName]uint16, len(syncers))
-	for bidderName, syncer := range syncers {
-		if syncer.GDPRVendorID() != 0 {
-			gdprAwareSyncers[bidderName] = syncer.GDPRVendorID()
-		}
-	}
-	return gdprAwareSyncers
-}
-
 type Syncer struct {
-	familyName   string
-	gdprVendorID uint16
-	urlTemplate  *template.Template
-	syncType     SyncType
+	familyName  string
+	syncType    SyncType
+	urlTemplate *template.Template
 }
 
-func NewSyncer(familyName string, vendorID uint16, urlTemplate *template.Template, syncType SyncType) *Syncer {
+func NewSyncer(familyName string, urlTemplate *template.Template, syncType SyncType) *Syncer {
 	return &Syncer{
-		familyName:   familyName,
-		gdprVendorID: vendorID,
-		urlTemplate:  urlTemplate,
-		syncType:     syncType,
+		familyName:  familyName,
+		urlTemplate: urlTemplate,
+		syncType:    syncType,
 	}
 }
 
@@ -62,7 +49,3 @@ func (s *Syncer) GetUsersyncInfo(privacyPolicies privacy.Policies) (*usersync.Us
 func (s *Syncer) FamilyName() string {
 	return s.familyName
 }
-
-func (s *Syncer) GDPRVendorID() uint16 {
-	return s.gdprVendorID
-}
diff --git a/adapters/tappx/usersync.go b/adapters/tappx/usersync.go
index 7bf6b9a6..01477c35 100644
--- a/adapters/tappx/usersync.go
+++ b/adapters/tappx/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewTappxSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("tappx", 628, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("tappx", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/telaria/usersync.go b/adapters/telaria/usersync.go
index e3f76f6e..76be6202 100644
--- a/adapters/telaria/usersync.go
+++ b/adapters/telaria/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewTelariaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("telaria", 202, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("telaria", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/triplelift/usersync.go b/adapters/triplelift/usersync.go
index 5cb524be..4a47615b 100644
--- a/adapters/triplelift/usersync.go
+++ b/adapters/triplelift/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewTripleliftSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("triplelift", 28, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("triplelift", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/triplelift_native/usersync.go b/adapters/triplelift_native/usersync.go
index b7587b77..2a07740a 100644
--- a/adapters/triplelift_native/usersync.go
+++ b/adapters/triplelift_native/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewTripleliftSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("triplelift", 28, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("triplelift", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/trustx/usersync.go b/adapters/trustx/usersync.go
index a617cd71..a738e8e9 100644
--- a/adapters/trustx/usersync.go
+++ b/adapters/trustx/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewTrustXSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("trustx", 686, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("trustx", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/ucfunnel/usersync.go b/adapters/ucfunnel/usersync.go
index 92eba0d7..0ae9948d 100644
--- a/adapters/ucfunnel/usersync.go
+++ b/adapters/ucfunnel/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewUcfunnelSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("ucfunnel", 607, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("ucfunnel", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/unruly/usersync.go b/adapters/unruly/usersync.go
index c90052a4..5dc60c85 100644
--- a/adapters/unruly/usersync.go
+++ b/adapters/unruly/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewUnrulySyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("unruly", 162, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("unruly", temp, adapters.SyncTypeIframe)
 }
diff --git a/adapters/valueimpression/usersync.go b/adapters/valueimpression/usersync.go
index 34addbc0..08490a5e 100644
--- a/adapters/valueimpression/usersync.go
+++ b/adapters/valueimpression/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewValueImpressionSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("valueimpression", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("valueimpression", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/verizonmedia/usersync.go b/adapters/verizonmedia/usersync.go
index 31fb12a2..2c7354d1 100644
--- a/adapters/verizonmedia/usersync.go
+++ b/adapters/verizonmedia/usersync.go
@@ -1,11 +1,12 @@
 package verizonmedia
 
 import (
+	"text/template"
+
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/usersync"
-	"text/template"
 )
 
 func NewVerizonMediaSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("verizonmedia", 25, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("verizonmedia", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/visx/usersync.go b/adapters/visx/usersync.go
index fe1f5a42..dc143570 100644
--- a/adapters/visx/usersync.go
+++ b/adapters/visx/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewVisxSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("visx", 154, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("visx", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/vrtcal/usersync.go b/adapters/vrtcal/usersync.go
index 04e52955..8a6ddc0c 100644
--- a/adapters/vrtcal/usersync.go
+++ b/adapters/vrtcal/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewVrtcalSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("vrtcal", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("vrtcal", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/yieldlab/usersync.go b/adapters/yieldlab/usersync.go
index 3ee9a3fd..90507e31 100644
--- a/adapters/yieldlab/usersync.go
+++ b/adapters/yieldlab/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewYieldlabSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("yieldlab", 70, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("yieldlab", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/yieldmo/usersync.go b/adapters/yieldmo/usersync.go
index 041e7e8f..d06caa90 100644
--- a/adapters/yieldmo/usersync.go
+++ b/adapters/yieldmo/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewYieldmoSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("yieldmo", 173, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("yieldmo", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/yieldone/usersync.go b/adapters/yieldone/usersync.go
index bc9d1b32..4d5d8283 100644
--- a/adapters/yieldone/usersync.go
+++ b/adapters/yieldone/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewYieldoneSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("yieldone", 0, temp, adapters.SyncTypeRedirect)
+	return adapters.NewSyncer("yieldone", temp, adapters.SyncTypeRedirect)
 }
diff --git a/adapters/zeroclickfraud/usersync.go b/adapters/zeroclickfraud/usersync.go
index 833524e4..41c58981 100644
--- a/adapters/zeroclickfraud/usersync.go
+++ b/adapters/zeroclickfraud/usersync.go
@@ -8,5 +8,5 @@ import (
 )
 
 func NewZeroClickFraudSyncer(temp *template.Template) usersync.Usersyncer {
-	return adapters.NewSyncer("zeroclickfraud", 0, temp, adapters.SyncTypeIframe)
+	return adapters.NewSyncer("zeroclickfraud", temp, adapters.SyncTypeIframe)
 }
diff --git a/config/bidderinfo.go b/config/bidderinfo.go
index 4af8a97c..9eff288f 100644
--- a/config/bidderinfo.go
+++ b/config/bidderinfo.go
@@ -19,6 +19,7 @@ type BidderInfo struct {
 	Capabilities            *CapabilitiesInfo `yaml:"capabilities"`
 	ModifyingVastXmlAllowed bool              `yaml:"modifyingVastXmlAllowed"`
 	Debug                   *DebugInfo        `yaml:"debug,omitempty"`
+	GVLVendorID             uint16            `yaml:"gvlVendorID,omitempty"`
 }
 
 // MaintainerInfo is the support email address for a bidder.
@@ -43,13 +44,13 @@ type DebugInfo struct {
 }
 
 // LoadBidderInfoFromDisk parses all static/bidder-info/{bidder}.yaml files from the file system.
-func LoadBidderInfoFromDisk(path string, adapterConfigs map[string]Adapter, bidders []string) (map[string]BidderInfo, error) {
+func LoadBidderInfoFromDisk(path string, adapterConfigs map[string]Adapter, bidders []string) (BidderInfos, error) {
 	reader := infoReaderFromDisk{path}
 	return loadBidderInfo(reader, adapterConfigs, bidders)
 }
 
-func loadBidderInfo(r infoReader, adapterConfigs map[string]Adapter, bidders []string) (map[string]BidderInfo, error) {
-	infos := map[string]BidderInfo{}
+func loadBidderInfo(r infoReader, adapterConfigs map[string]Adapter, bidders []string) (BidderInfos, error) {
+	infos := BidderInfos{}
 
 	for _, bidder := range bidders {
 		data, err := r.Read(bidder)
@@ -86,3 +87,15 @@ func (r infoReaderFromDisk) Read(bidder string) ([]byte, error) {
 	path := fmt.Sprintf("%v/%v.yaml", r.path, bidder)
 	return ioutil.ReadFile(path)
 }
+
+// ToGVLVendorIDMap transforms a BidderInfos object to a map of bidder names to GVL id. Disabled
+// bidders are omitted from the result.
+func (infos BidderInfos) ToGVLVendorIDMap() map[openrtb_ext.BidderName]uint16 {
+	m := make(map[openrtb_ext.BidderName]uint16, len(infos))
+	for name, info := range infos {
+		if info.Enabled && info.GVLVendorID != 0 {
+			m[openrtb_ext.BidderName(name)] = info.GVLVendorID
+		}
+	}
+	return m
+}
diff --git a/config/config.go b/config/config.go
index 2abdd117..22ce8faf 100644
--- a/config/config.go
+++ b/config/config.go
@@ -577,6 +577,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdman, "https://sync.admanmedia.com/pbs.gif?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadman%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BUID%5D")
 	// 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.BidderAdyoulike, "http://visitor.omnitagjs.com/visitor/bsync?uid=19340f4f097d16f41f34fc0274981ca4&name=PrebidServer&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadyoulike%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BBUYER_USERID%5D")
 	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")
@@ -797,7 +798,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	// Disabling adapters by default that require some specific config params.
 	// If you're using one of these, make sure you check out the documentation (https://github.com/prebid/prebid-server/tree/master/docs/bidders)
 	// for them and specify all the parameters they need for them to work correctly.
-	v.SetDefault("adapters.33across.endpoint", "http://ssc.33across.com/api/v1/hb")
+	v.SetDefault("adapters.33across.endpoint", "https://ssc.33across.com/api/v1/s2s")
 	v.SetDefault("adapters.33across.partner_id", "")
 	v.SetDefault("adapters.acuityads.endpoint", "http://{{.Host}}.admanmedia.com/bid?token={{.AccountID}}")
 	v.SetDefault("adapters.adform.endpoint", "https://adx.adform.net/adx")
@@ -815,6 +816,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	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.adyoulike.endpoint", "https://broker-preprod.omnitagjs.com/broker/bid?partnerId=19340f4f097d16f41f34fc0274981ca4")
 	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")
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 290b06cb..35230315 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -830,19 +830,15 @@ func (deps *endpointDeps) validateImpExt(imp *openrtb.Imp, aliases map[string]st
 		return []error{err}
 	}
 
-	// Also accept bidder exts within imp[...].ext.prebid.bidder
-	// NOTE: This is not part of the official API yet, so we are not expecting clients
-	// to migrate from imp[...].ext.${BIDDER} to imp[...].ext.prebid.bidder.${BIDDER}
-	// at this time
-	// https://github.com/prebid/prebid-server/pull/846#issuecomment-476352224
-	if rawPrebidExt, ok := bidderExts[openrtb_ext.PrebidExtKey]; ok {
-		var prebidExt openrtb_ext.ExtImpPrebid
-		if err := json.Unmarshal(rawPrebidExt, &prebidExt); err == nil && prebidExt.Bidder != nil {
-			for bidder, ext := range prebidExt.Bidder {
+	// Prefer bidder params from request.imp.ext.prebid.bidder.BIDDER over request.imp.ext.BIDDER
+	// to avoid confusion beteween prebid specific adapter config and other ext protocols.
+	if extPrebidJSON, ok := bidderExts[openrtb_ext.PrebidExtKey]; ok {
+		var extPrebid openrtb_ext.ExtImpPrebid
+		if err := json.Unmarshal(extPrebidJSON, &extPrebid); err == nil && extPrebid.Bidder != nil {
+			for bidder, ext := range extPrebid.Bidder {
 				if ext == nil {
 					continue
 				}
-
 				bidderExts[bidder] = ext
 			}
 		}
@@ -893,13 +889,18 @@ func (deps *endpointDeps) validateImpExt(imp *openrtb.Imp, aliases map[string]st
 	return errL
 }
 
+// isBidderToValidate determines if the bidder name in request.imp[].prebid should be validated.
 func isBidderToValidate(bidder string) bool {
-	// PrebidExtKey is a special case for the prebid config section and is not considered a bidder.
-
-	// FirstPartyDataContextExtKey is a special case for the first party data context section
-	// and is not considered a bidder.
-
-	return bidder != openrtb_ext.PrebidExtKey && bidder != openrtb_ext.FirstPartyDataContextExtKey
+	switch openrtb_ext.BidderName(bidder) {
+	case openrtb_ext.BidderReservedContext:
+		return false
+	case openrtb_ext.BidderReservedPrebid:
+		return false
+	case openrtb_ext.BidderReservedSKAdN:
+		return false
+	default:
+		return true
+	}
 }
 
 func (deps *endpointDeps) parseBidExt(ext json.RawMessage) (*openrtb_ext.ExtRequest, error) {
@@ -914,12 +915,17 @@ func (deps *endpointDeps) parseBidExt(ext json.RawMessage) (*openrtb_ext.ExtRequ
 }
 
 func (deps *endpointDeps) validateAliases(aliases map[string]string) error {
-	for thisAlias, coreBidder := range aliases {
+	for alias, coreBidder := range aliases {
+		if _, isCoreBidderDisabled := deps.disabledBidders[coreBidder]; isCoreBidderDisabled {
+			return fmt.Errorf("request.ext.prebid.aliases.%s refers to disabled bidder: %s", alias, coreBidder)
+		}
+
 		if _, isCoreBidder := deps.bidderMap[coreBidder]; !isCoreBidder {
-			return fmt.Errorf("request.ext.prebid.aliases.%s refers to unknown bidder: %s", thisAlias, coreBidder)
+			return fmt.Errorf("request.ext.prebid.aliases.%s refers to unknown bidder: %s", alias, coreBidder)
 		}
-		if thisAlias == coreBidder {
-			return fmt.Errorf("request.ext.prebid.aliases.%s defines a no-op alias. Choose a different alias, or remove this entry.", thisAlias)
+
+		if alias == coreBidder {
+			return fmt.Errorf("request.ext.prebid.aliases.%s defines a no-op alias. Choose a different alias, or remove this entry.", alias)
 		}
 	}
 	return nil
diff --git a/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json b/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json
index f4379dc0..86239308 100644
--- a/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json
+++ b/endpoints/openrtb2/sample-requests/disabled/bad/bad-alias.json
@@ -1,7 +1,7 @@
 {
   "description": "Request comes with an alias to a disabled bidder, we should throw error",
   "config": {
-    "disabledAdapters": ["appnexus", "rubicon"]
+    "disabledAdapters": ["appnexus"]
   },
   "mockBidRequest": {
     "id": "some-request-id",
@@ -32,5 +32,5 @@
     }
   },
   "expectedReturnCode": 400,
-  "expectedErrorMessage": "Invalid request: request.ext.prebid.aliases.test1 refers to unknown bidder: appnexus\n"
+  "expectedErrorMessage": "Invalid request: request.ext.prebid.aliases.test1 refers to disabled bidder: appnexus\n"
 }
diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/skadn.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/skadn.json
new file mode 100644
index 00000000..e238f3c0
--- /dev/null
+++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/skadn.json
@@ -0,0 +1,48 @@
+{
+    "description": "The imp.ext.skadn field is valid for Apple's SKAdNetwork and should be exempt from bidder name validation.",
+
+    "mockBidRequest": {
+        "id": "some-request-id",
+        "site": {
+            "page": "test.somepage.com"
+        },
+        "imp": [{
+            "id": "some-imp-id",
+            "banner": {
+                "format": [{
+                    "w": 600,
+                    "h": 500
+                }, {
+                    "w": 300,
+                    "h": 600
+                }]
+            },
+            "ext": {
+                "prebid": {
+                    "bidder": {
+                        "appnexus": {
+                            "placementId": 12883451
+                        }
+                    }
+                },
+                "skadn": {
+                    "anyMember": "anyValue"
+                }
+            }
+        }]
+    },
+    "expectedBidResponse": {
+        "id": "some-request-id",
+        "seatbid": [{
+            "bid": [{
+                "id": "appnexus-bid",
+                "impid": "",
+                "price": 0
+            }],
+            "seat": "appnexus-bids"
+        }],
+        "bidid": "test bid id",
+        "nbr": 0
+    },
+    "expectedReturnCode": 200
+}
\ No newline at end of file
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 8d0c0a40..46c96706 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -19,6 +19,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/adtarget"
 	"github.com/prebid/prebid-server/adapters/adtelligent"
 	"github.com/prebid/prebid-server/adapters/advangelists"
+	"github.com/prebid/prebid-server/adapters/adyoulike"
 	"github.com/prebid/prebid-server/adapters/aja"
 	"github.com/prebid/prebid-server/adapters/amx"
 	"github.com/prebid/prebid-server/adapters/applogy"
@@ -126,6 +127,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderAdtarget:         adtarget.Builder,
 		openrtb_ext.BidderAdtelligent:      adtelligent.Builder,
 		openrtb_ext.BidderAdvangelists:     advangelists.Builder,
+		openrtb_ext.BidderAdyoulike:        adyoulike.Builder,
 		openrtb_ext.BidderAJA:              aja.Builder,
 		openrtb_ext.BidderAMX:              amx.Builder,
 		openrtb_ext.BidderApplogy:          applogy.Builder,
diff --git a/exchange/bidder.go b/exchange/bidder.go
index f916e205..6df5fafb 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -83,10 +83,6 @@ type pbsOrtbSeatBid struct {
 	// httpCalls is the list of debugging info. It should only be populated if the request.test == 1.
 	// This will become response.ext.debug.httpcalls.{bidder} on the final Response.
 	httpCalls []*openrtb_ext.ExtHttpCall
-	// ext contains the extension for this seatbid.
-	// if len(bids) > 0, this will become response.seatbid[i].ext.{bidder} on the final OpenRTB response.
-	// if len(bids) == 0, this will be ignored because the OpenRTB spec doesn't allow a SeatBid with 0 Bids.
-	ext json.RawMessage
 }
 
 // adaptBidder converts an adapters.Bidder into an exchange.adaptedBidder.
diff --git a/exchange/exchange.go b/exchange/exchange.go
index b4fa3a61..45081c16 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -788,25 +788,9 @@ func (e *exchange) makeExtBidResponse(adapterBids map[openrtb_ext.BidderName]*pb
 // Return an openrtb seatBid for a bidder
 // BuildBidResponse is responsible for ensuring nil bid seatbids are not included
 func (e *exchange) makeSeatBid(adapterBid *pbsOrtbSeatBid, adapter openrtb_ext.BidderName, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, returnCreative bool) *openrtb.SeatBid {
-	seatBid := new(openrtb.SeatBid)
-	seatBid.Seat = adapter.String()
-	// Prebid cannot support roadblocking
-	seatBid.Group = 0
-
-	if len(adapterBid.ext) > 0 {
-		sbExt := ExtSeatBid{
-			Bidder: adapterBid.ext,
-		}
-
-		ext, err := json.Marshal(sbExt)
-		if err != nil {
-			extError := openrtb_ext.ExtBidderError{
-				Code:    errortypes.ReadCode(err),
-				Message: fmt.Sprintf("Error writing SeatBid.Ext: %s", err.Error()),
-			}
-			adapterExtra[adapter].Errors = append(adapterExtra[adapter].Errors, extError)
-		}
-		seatBid.Ext = ext
+	seatBid := &openrtb.SeatBid{
+		Seat:  adapter.String(),
+		Group: 0, // Prebid cannot support roadblocking
 	}
 
 	var errList []error
@@ -818,39 +802,54 @@ func (e *exchange) makeSeatBid(adapterBid *pbsOrtbSeatBid, adapter openrtb_ext.B
 	return seatBid
 }
 
-// Create the Bid array inside of SeatBid
-func (e *exchange) makeBid(Bids []*pbsOrtbBid, auc *auction, returnCreative bool) ([]openrtb.Bid, []error) {
-	bids := make([]openrtb.Bid, 0, len(Bids))
-	errList := make([]error, 0, 1)
-	for _, thisBid := range Bids {
-		bidExt := &openrtb_ext.ExtBid{
-			Bidder: thisBid.bid.Ext,
-			Prebid: &openrtb_ext.ExtBidPrebid{
-				Targeting:         thisBid.bidTargets,
-				Type:              thisBid.bidType,
-				Video:             thisBid.bidVideo,
-				Events:            thisBid.bidEvents,
-				DealPriority:      thisBid.dealPriority,
-				DealTierSatisfied: thisBid.dealTierSatisfied,
-			},
+func (e *exchange) makeBid(bids []*pbsOrtbBid, auc *auction, returnCreative bool) ([]openrtb.Bid, []error) {
+	result := make([]openrtb.Bid, 0, len(bids))
+	errs := make([]error, 0, 1)
+
+	for _, bid := range bids {
+		bidExtPrebid := &openrtb_ext.ExtBidPrebid{
+			DealPriority:      bid.dealPriority,
+			DealTierSatisfied: bid.dealTierSatisfied,
+			Events:            bid.bidEvents,
+			Targeting:         bid.bidTargets,
+			Type:              bid.bidType,
+			Video:             bid.bidVideo,
 		}
-		if cacheInfo, found := e.getBidCacheInfo(thisBid, auc); found {
-			bidExt.Prebid.Cache = &openrtb_ext.ExtBidPrebidCache{
+
+		if cacheInfo, found := e.getBidCacheInfo(bid, auc); found {
+			bidExtPrebid.Cache = &openrtb_ext.ExtBidPrebidCache{
 				Bids: &cacheInfo,
 			}
 		}
-		ext, err := json.Marshal(bidExt)
-		if err != nil {
-			errList = append(errList, err)
+
+		if bidExtJSON, err := makeBidExtJSON(bid.bid.Ext, bidExtPrebid); err != nil {
+			errs = append(errs, err)
 		} else {
-			bids = append(bids, *thisBid.bid)
-			bids[len(bids)-1].Ext = ext
+			result = append(result, *bid.bid)
+			resultBid := &result[len(result)-1]
+			resultBid.Ext = bidExtJSON
 			if !returnCreative {
-				bids[len(bids)-1].AdM = ""
+				resultBid.AdM = ""
 			}
 		}
 	}
-	return bids, errList
+	return result, errs
+}
+
+func makeBidExtJSON(ext json.RawMessage, prebid *openrtb_ext.ExtBidPrebid) (json.RawMessage, error) {
+	// no existing bid.ext. generate a bid.ext with just our prebid section populated.
+	if len(ext) == 0 {
+		bidExt := &openrtb_ext.ExtBid{Prebid: prebid}
+		return json.Marshal(bidExt)
+	}
+
+	// update existing bid.ext with our prebid section. if bid.ext.prebid already exists, it will be overwritten.
+	var extMap map[string]interface{}
+	if err := json.Unmarshal(ext, &extMap); err != nil {
+		return nil, err
+	}
+	extMap[openrtb_ext.PrebidExtKey] = prebid
+	return json.Marshal(extMap)
 }
 
 // If bid got cached inside `(a *auction) doCache(ctx context.Context, cache prebid_cache_client.Client, targData *targetData, bidRequest *openrtb.BidRequest, ttlBuffer int64, defaultTTLs *config.DefaultTTLs, bidCategory map[string]string)`,
diff --git a/exchange/seatbid.go b/exchange/seatbid.go
deleted file mode 100644
index b6751274..00000000
--- a/exchange/seatbid.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package exchange
-
-import "encoding/json"
-
-// ExtSeatBid defines the contract for bidresponse.seatbid.ext
-type ExtSeatBid struct {
-	Bidder json.RawMessage `json:"bidder,omitempty"`
-}
diff --git a/exchange/utils.go b/exchange/utils.go
index 8d4c0fac..4ca02149 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -59,8 +59,9 @@ func cleanOpenRTBRequests(ctx context.Context,
 	usersyncIfAmbiguous bool,
 	privacyConfig config.Privacy) (bidderRequests []BidderRequest, privacyLabels metrics.PrivacyLabels, errs []error) {
 
-	impsByBidder, errs := splitImps(req.BidRequest.Imp)
-	if len(errs) > 0 {
+	impsByBidder, err := splitImps(req.BidRequest.Imp)
+	if err != nil {
+		errs = []error{err}
 		return
 	}
 
@@ -327,106 +328,99 @@ func extractBuyerUIDs(user *openrtb.User) (map[string]string, error) {
 // The "imp.ext" value of the rubicon Imp will only contain the "prebid" values, and "rubicon" value at the "bidder" key.
 //
 // The goal here is so that Bidders only get Imps and Imp.Ext values which are intended for them.
-func splitImps(imps []openrtb.Imp) (map[string][]openrtb.Imp, []error) {
-	impExts, err := parseImpExts(imps)
-	if err != nil {
-		return nil, []error{err}
-	}
+func splitImps(imps []openrtb.Imp) (map[string][]openrtb.Imp, error) {
+	bidderImps := make(map[string][]openrtb.Imp)
 
-	splitImps := make(map[string][]openrtb.Imp, len(imps))
-	var errList []error
+	for i, imp := range imps {
+		var impExt map[string]json.RawMessage
+		if err := json.Unmarshal(imp.Ext, &impExt); err != nil {
+			return nil, fmt.Errorf("invalid json for imp[%d]: %v", i, err)
+		}
 
-	for i := 0; i < len(imps); i++ {
-		imp := imps[i]
-		impExt := impExts[i]
+		var impExtPrebid map[string]json.RawMessage
+		if impExtPrebidJSON, exists := impExt[openrtb_ext.PrebidExtKey]; exists {
+			// validation already performed by impExt unmarshal. no error is possible here, proven by tests.
+			json.Unmarshal(impExtPrebidJSON, &impExtPrebid)
+		}
 
-		var firstPartyDataContext json.RawMessage
-		if context, exists := impExt[openrtb_ext.FirstPartyDataContextExtKey]; exists {
-			firstPartyDataContext = context
+		var impExtPrebidBidder map[string]json.RawMessage
+		if impExtPrebidBidderJSON, exists := impExtPrebid[openrtb_ext.PrebidExtBidderKey]; exists {
+			// validation already performed by impExt unmarshal. no error is possible here, proven by tests.
+			json.Unmarshal(impExtPrebidBidderJSON, &impExtPrebidBidder)
 		}
 
-		rawPrebidExt, ok := impExt[openrtb_ext.PrebidExtKey]
+		sanitizedImpExt, err := createSanitizedImpExt(impExt, impExtPrebid)
+		if err != nil {
+			return nil, fmt.Errorf("unable to remove other bidder fields for imp[%d]: %v", i, err)
+		}
 
-		if ok {
-			var prebidExt openrtb_ext.ExtImpPrebid
+		for bidder, bidderExt := range extractBidderExts(impExt, impExtPrebidBidder) {
+			impCopy := imp
 
-			if err := json.Unmarshal(rawPrebidExt, &prebidExt); err == nil && prebidExt.Bidder != nil {
-				if errs := sanitizedImpCopy(&imp, prebidExt.Bidder, rawPrebidExt, firstPartyDataContext, &splitImps); errs != nil {
-					errList = append(errList, errs...)
-				}
+			sanitizedImpExt[openrtb_ext.PrebidExtBidderKey] = bidderExt
 
-				continue
+			impExtJSON, err := json.Marshal(sanitizedImpExt)
+			if err != nil {
+				return nil, fmt.Errorf("unable to remove other bidder fields for imp[%d]: cannot marshal ext: %v", i, err)
 			}
-		}
+			impCopy.Ext = impExtJSON
 
-		if errs := sanitizedImpCopy(&imp, impExt, rawPrebidExt, firstPartyDataContext, &splitImps); errs != nil {
-			errList = append(errList, errs...)
+			bidderImps[bidder] = append(bidderImps[bidder], impCopy)
 		}
 	}
 
-	return splitImps, nil
+	return bidderImps, nil
 }
 
-// sanitizedImpCopy returns a copy of imp with its ext filtered so that only "prebid", "context", and bidder params exist.
-// It will not mutate the input imp.
-// This function will write the new imps to the output map passed in
-func sanitizedImpCopy(imp *openrtb.Imp,
-	bidderExts map[string]json.RawMessage,
-	rawPrebidExt json.RawMessage,
-	firstPartyDataContext json.RawMessage,
-	out *map[string][]openrtb.Imp) []error {
-
-	var prebidExt map[string]json.RawMessage
-	var errs []error
-
-	if err := json.Unmarshal(rawPrebidExt, &prebidExt); err == nil {
-		// Remove the entire bidder field. We will already have the content we need in bidderExts. We
-		// don't want to include other demand partners' bidder params in the sanitized imp.
-		if _, hasBidderField := prebidExt["bidder"]; hasBidderField {
-			delete(prebidExt, "bidder")
+func createSanitizedImpExt(impExt, impExtPrebid map[string]json.RawMessage) (map[string]json.RawMessage, error) {
+	sanitizedImpExt := make(map[string]json.RawMessage, 3)
 
-			var err error
-			if rawPrebidExt, err = json.Marshal(prebidExt); err != nil {
-				errs = append(errs, err)
-			}
+	delete(impExtPrebid, openrtb_ext.PrebidExtBidderKey)
+	if len(impExtPrebid) > 0 {
+		if impExtPrebidJSON, err := json.Marshal(impExtPrebid); err == nil {
+			sanitizedImpExt[openrtb_ext.PrebidExtKey] = impExtPrebidJSON
+		} else {
+			return nil, fmt.Errorf("cannot marshal ext.prebid: %v", err)
 		}
 	}
 
-	for bidder, ext := range bidderExts {
-		if bidder == openrtb_ext.PrebidExtKey || bidder == openrtb_ext.FirstPartyDataContextExtKey {
-			continue
-		}
+	if v, exists := impExt[openrtb_ext.FirstPartyDataContextExtKey]; exists {
+		sanitizedImpExt[openrtb_ext.FirstPartyDataContextExtKey] = v
+	}
 
-		impCopy := *imp
-		newExt := make(map[string]json.RawMessage, 3)
+	if v, exists := impExt[openrtb_ext.SKAdNExtKey]; exists {
+		sanitizedImpExt[openrtb_ext.SKAdNExtKey] = v
+	}
 
-		newExt["bidder"] = ext
+	return sanitizedImpExt, nil
+}
 
-		if rawPrebidExt != nil {
-			newExt[openrtb_ext.PrebidExtKey] = rawPrebidExt
-		}
+func extractBidderExts(impExt, impExtPrebidBidders map[string]json.RawMessage) map[string]json.RawMessage {
+	bidderExts := make(map[string]json.RawMessage)
 
-		if len(firstPartyDataContext) > 0 {
-			newExt[openrtb_ext.FirstPartyDataContextExtKey] = firstPartyDataContext
-		}
+	// prefer imp.ext.prebid.bidder.BIDDER
+	for bidder, bidderExt := range impExtPrebidBidders {
+		bidderExts[bidder] = bidderExt
+	}
 
-		rawExt, err := json.Marshal(newExt)
-		if err != nil {
-			errs = append(errs, err)
+	// fallback to imp.BIDDER
+	for bidder, bidderExt := range impExt {
+		if isSpecialField(bidder) {
 			continue
 		}
 
-		impCopy.Ext = rawExt
-
-		otherImps, _ := (*out)[bidder]
-		(*out)[bidder] = append(otherImps, impCopy)
+		if _, exists := bidderExts[bidder]; !exists {
+			bidderExts[bidder] = bidderExt
+		}
 	}
 
-	if len(errs) > 0 {
-		return errs
-	}
+	return bidderExts
+}
 
-	return nil
+func isSpecialField(bidder string) bool {
+	return bidder == openrtb_ext.FirstPartyDataContextExtKey ||
+		bidder == openrtb_ext.SKAdNExtKey ||
+		bidder == openrtb_ext.PrebidExtKey
 }
 
 // prepareUser changes req.User so that it's ready for the given bidder.
@@ -564,21 +558,6 @@ func resolveBidder(bidder string, aliases map[string]string) openrtb_ext.BidderN
 	return openrtb_ext.BidderName(bidder)
 }
 
-// parseImpExts does a partial-unmarshal of the imp[].Ext field.
-// The keys in the returned map are expected to be "prebid", "context", CoreBidderNames, or Aliases for this request.
-func parseImpExts(imps []openrtb.Imp) ([]map[string]json.RawMessage, error) {
-	exts := make([]map[string]json.RawMessage, len(imps))
-	// Loop over every impression in the request
-	for i := 0; i < len(imps); i++ {
-		// Unpack each set of extensions found in the Imp array
-		err := json.Unmarshal(imps[i].Ext, &exts[i])
-		if err != nil {
-			return nil, fmt.Errorf("Error unpacking extensions for Imp[%d]: %s", i, err.Error())
-		}
-	}
-	return exts, nil
-}
-
 // parseAliases parses the aliases from the BidRequest
 func parseAliases(orig *openrtb.BidRequest) (map[string]string, []error) {
 	var aliases map[string]string
diff --git a/openrtb_ext/bid.go b/openrtb_ext/bid.go
index 8f4d7a09..7d787cf8 100644
--- a/openrtb_ext/bid.go
+++ b/openrtb_ext/bid.go
@@ -1,14 +1,12 @@
 package openrtb_ext
 
 import (
-	"encoding/json"
 	"fmt"
 )
 
 // ExtBid defines the contract for bidresponse.seatbid.bid[i].ext
 type ExtBid struct {
-	Prebid *ExtBidPrebid   `json:"prebid,omitempty"`
-	Bidder json.RawMessage `json:"bidder,omitempty"`
+	Prebid *ExtBidPrebid `json:"prebid,omitempty"`
 }
 
 // ExtBidPrebid defines the contract for bidresponse.seatbid.bid[i].ext.prebid
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 600e130b..e03c234b 100755
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -35,7 +35,7 @@ const (
 	BidderReservedData    BidderName = "data"    // Reserved for first party data.
 	BidderReservedGeneral BidderName = "general" // Reserved for non-bidder specific messages when using a map keyed on the bidder name.
 	BidderReservedPrebid  BidderName = "prebid"  // Reserved for Prebid Server configuration.
-	BidderReservedSKAdN   BidderName = "skadn"   // Reserved for SKAdNetwork OpenRTB extension.
+	BidderReservedSKAdN   BidderName = "skadn"   // Reserved for Apple's SKAdNetwork OpenRTB extension.
 )
 
 // IsBidderNameReserved returns true if the specified name is a case insensitive match for a reserved bidder name.
@@ -90,6 +90,7 @@ const (
 	BidderAdtarget         BidderName = "adtarget"
 	BidderAdtelligent      BidderName = "adtelligent"
 	BidderAdvangelists     BidderName = "advangelists"
+	BidderAdyoulike        BidderName = "adyoulike"
 	BidderAJA              BidderName = "aja"
 	BidderAMX              BidderName = "amx"
 	BidderApplogy          BidderName = "applogy"
@@ -197,6 +198,7 @@ func CoreBidderNames() []BidderName {
 		BidderAdtarget,
 		BidderAdtelligent,
 		BidderAdvangelists,
+		BidderAdyoulike,
 		BidderAJA,
 		BidderAMX,
 		BidderApplogy,
diff --git a/openrtb_ext/device.go b/openrtb_ext/device.go
index eb465511..cc06f380 100644
--- a/openrtb_ext/device.go
+++ b/openrtb_ext/device.go
@@ -12,6 +12,9 @@ import (
 // PrebidExtKey represents the prebid extension key used in requests
 const PrebidExtKey = "prebid"
 
+// PrebidExtBidderKey represents the field name within request.imp.ext.prebid reserved for bidder params.
+const PrebidExtBidderKey = "bidder"
+
 // ExtDevice defines the contract for bidrequest.device.ext
 type ExtDevice struct {
 	// Attribute:
diff --git a/openrtb_ext/imp_adyoulike.go b/openrtb_ext/imp_adyoulike.go
new file mode 100644
index 00000000..67a94123
--- /dev/null
+++ b/openrtb_ext/imp_adyoulike.go
@@ -0,0 +1,18 @@
+package openrtb_ext
+
+// ExtImpAdyoulike defines the contract for bidrequest.imp[i].ext.adyoulike
+type ExtImpAdyoulike struct {
+	// placementId, only mandatory field
+	PlacementId string `json:"placement"`
+
+	// Id of the forced campaign
+	Campaign string `json:"campaign"`
+	// Id of the forced track
+	Track string `json:"track"`
+	// Id of the forced creative
+	Creative string `json:"creative"`
+	// Context of the campaign values [SSP|AdServer]
+	Source string `json:"source"`
+	// Abitrary Id used for debug purpose
+	Debug string `json:"debug"`
+}
diff --git a/openrtb_ext/request.go b/openrtb_ext/request.go
index 124e050a..b2bb25e7 100644
--- a/openrtb_ext/request.go
+++ b/openrtb_ext/request.go
@@ -5,9 +5,12 @@ import (
 	"errors"
 )
 
-// FirstPartyDataContextExtKey defines the field name within bidrequest.ext reserved
-// for first party data support.
-const FirstPartyDataContextExtKey string = "context"
+// FirstPartyDataContextExtKey defines the field name within request.ext reserved for first party data.
+const FirstPartyDataContextExtKey = "context"
+
+// SKAdNExtKey defines the field name within request.ext reserved for Apple's SKAdNetwork.
+const SKAdNExtKey = "skadn"
+
 const MaxDecimalFigures int = 15
 
 // ExtRequest defines the contract for bidrequest.ext
diff --git a/router/router.go b/router/router.go
index 7a088bbf..0920f1d6 100644
--- a/router/router.go
+++ b/router/router.go
@@ -217,7 +217,6 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R
 	// Metrics engine
 	r.MetricsEngine = metricsConf.NewMetricsEngine(cfg, legacyBidderList)
 	db, shutdown, fetcher, ampFetcher, accounts, categoriesFetcher, videoFetcher := storedRequestsConf.NewStoredRequests(cfg, r.MetricsEngine, generalHttpClient, r.Router)
-
 	// todo(zachbadgett): better shutdown
 	r.Shutdown = shutdown
 	if err := loadDataCache(cfg, db); err != nil {
@@ -246,7 +245,8 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R
 	}
 
 	syncers := usersyncers.NewSyncerMap(cfg)
-	gdprPerms := gdpr.NewPermissions(context.Background(), cfg.GDPR, adapters.GDPRAwareSyncerIDs(syncers), generalHttpClient)
+	gvlVendorIDs := bidderInfos.ToGVLVendorIDMap()
+	gdprPerms := gdpr.NewPermissions(context.Background(), cfg.GDPR, gvlVendorIDs, generalHttpClient)
 
 	exchanges = newExchangeMap(cfg)
 	cacheClient := pbc.NewClient(cacheHttpClient, &cfg.CacheURL, &cfg.ExtCacheURL, r.MetricsEngine)
diff --git a/static/bidder-info/33across.yaml b/static/bidder-info/33across.yaml
index e3eea765..044cfe14 100644
--- a/static/bidder-info/33across.yaml
+++ b/static/bidder-info/33across.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "headerbidding@33across.com"
+gvlVendorID: 58
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/acuityads.yaml b/static/bidder-info/acuityads.yaml
index 9da1446d..9539e36b 100644
--- a/static/bidder-info/acuityads.yaml
+++ b/static/bidder-info/acuityads.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "integrations@acuityads.com"
+gvlVendorID: 231
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adform.yaml b/static/bidder-info/adform.yaml
index 4dce10b9..461714ac 100644
--- a/static/bidder-info/adform.yaml
+++ b/static/bidder-info/adform.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "scope.sspp@adform.com"
+gvlVendorID: 50
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adkernel.yaml b/static/bidder-info/adkernel.yaml
index 26f8c322..a78b3cde 100644
--- a/static/bidder-info/adkernel.yaml
+++ b/static/bidder-info/adkernel.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid-dev@adkernel.com"
+gvlVendorID: 14
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adkernelAdn.yaml b/static/bidder-info/adkernelAdn.yaml
index fd47367d..1f54f8e5 100644
--- a/static/bidder-info/adkernelAdn.yaml
+++ b/static/bidder-info/adkernelAdn.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid-dev@adkernel.com"
+gvlVendorID: 14
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adman.yaml b/static/bidder-info/adman.yaml
index 932ef2e4..2db7c075 100644
--- a/static/bidder-info/adman.yaml
+++ b/static/bidder-info/adman.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@admanmedia.com"
+gvlVendorID: 149
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/admixer.yaml b/static/bidder-info/admixer.yaml
index 64ad2024..9faf0eb3 100644
--- a/static/bidder-info/admixer.yaml
+++ b/static/bidder-info/admixer.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@admixer.net"
+gvlVendorID: 511
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adocean.yaml b/static/bidder-info/adocean.yaml
index 2f31fe92..b3a23718 100644
--- a/static/bidder-info/adocean.yaml
+++ b/static/bidder-info/adocean.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "aoteam@gemius.com"
+gvlVendorID: 328
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/adpone.yaml b/static/bidder-info/adpone.yaml
index 969983a1..7c5b4737 100644
--- a/static/bidder-info/adpone.yaml
+++ b/static/bidder-info/adpone.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "tech@adpone.com"
+gvlVendorID: 799
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adtelligent.yaml b/static/bidder-info/adtelligent.yaml
index 7a20d52b..30f55ea9 100644
--- a/static/bidder-info/adtelligent.yaml
+++ b/static/bidder-info/adtelligent.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "hb@adtelligent.com"
+gvlVendorID: 410
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/adyoulike.yaml b/static/bidder-info/adyoulike.yaml
new file mode 100644
index 00000000..d9b23d6c
--- /dev/null
+++ b/static/bidder-info/adyoulike.yaml
@@ -0,0 +1,10 @@
+maintainer:
+  email: "core@adyoulike.com"
+gvlVendorID: 259
+modifyingVastXmlAllowed: true
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+      - native
diff --git a/static/bidder-info/amx.yaml b/static/bidder-info/amx.yaml
index 3e20d209..f9fdfbb4 100644
--- a/static/bidder-info/amx.yaml
+++ b/static/bidder-info/amx.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@amxrtb.com"
+gvlVendorID: 737
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/appnexus.yaml b/static/bidder-info/appnexus.yaml
index f1e7ca23..f2f4a126 100644
--- a/static/bidder-info/appnexus.yaml
+++ b/static/bidder-info/appnexus.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid-server@xandr.com"
+gvlVendorID: 32
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/avocet.yaml b/static/bidder-info/avocet.yaml
index ea98982d..42147c96 100644
--- a/static/bidder-info/avocet.yaml
+++ b/static/bidder-info/avocet.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "developers@avocet.io"
+gvlVendorID: 63
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/beachfront.yaml b/static/bidder-info/beachfront.yaml
index 335545ff..06991698 100644
--- a/static/bidder-info/beachfront.yaml
+++ b/static/bidder-info/beachfront.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@beachfront.com"
+gvlVendorID: 335
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/beintoo.yaml b/static/bidder-info/beintoo.yaml
index fcca2922..905d89a4 100644
--- a/static/bidder-info/beintoo.yaml
+++ b/static/bidder-info/beintoo.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "adops@beintoo.com"
+gvlVendorID: 618
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/between.yaml b/static/bidder-info/between.yaml
index d317d275..71bd8ba6 100644
--- a/static/bidder-info/between.yaml
+++ b/static/bidder-info/between.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "buying@betweenx.com"
+gvlVendorID: 724
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/brightroll.yaml b/static/bidder-info/brightroll.yaml
index f913be6d..a2ea0c74 100644
--- a/static/bidder-info/brightroll.yaml
+++ b/static/bidder-info/brightroll.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "dsp-supply-prebid@verizonmedia.com"
+gvlVendorID: 25
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/connectad.yaml b/static/bidder-info/connectad.yaml
index 1b3e593d..fa0ae452 100644
--- a/static/bidder-info/connectad.yaml
+++ b/static/bidder-info/connectad.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "support@connectad.io"
+gvlVendorID: 138
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/consumable.yaml b/static/bidder-info/consumable.yaml
index f12ab2b4..e9b5f726 100644
--- a/static/bidder-info/consumable.yaml
+++ b/static/bidder-info/consumable.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "naffis@consumable.com"
+gvlVendorID: 591
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/conversant.yaml b/static/bidder-info/conversant.yaml
index 017f0e0c..aa3d3822 100644
--- a/static/bidder-info/conversant.yaml
+++ b/static/bidder-info/conversant.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "CNVR_PublisherIntegration@conversantmedia.com"
+gvlVendorID: 24
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/deepintent.yaml b/static/bidder-info/deepintent.yaml
index 490e161c..a8f17a55 100644
--- a/static/bidder-info/deepintent.yaml
+++ b/static/bidder-info/deepintent.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebiddev@deepintent.com"
+gvlVendorID: 541
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/dmx.yaml b/static/bidder-info/dmx.yaml
index 3ecb452f..d29d699d 100644
--- a/static/bidder-info/dmx.yaml
+++ b/static/bidder-info/dmx.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@districtm.net"
+gvlVendorID: 144
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/emx_digital.yaml b/static/bidder-info/emx_digital.yaml
index 49a06809..ec0d090f 100644
--- a/static/bidder-info/emx_digital.yaml
+++ b/static/bidder-info/emx_digital.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "adops@emxdigital.com"
+gvlVendorID: 183
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/engagebdr.yaml b/static/bidder-info/engagebdr.yaml
index 57c359e4..fd08367a 100644
--- a/static/bidder-info/engagebdr.yaml
+++ b/static/bidder-info/engagebdr.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "tech@engagebdr.com"
+gvlVendorID: 62
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/eplanning.yaml b/static/bidder-info/eplanning.yaml
index 907523d3..ab0b7609 100644
--- a/static/bidder-info/eplanning.yaml
+++ b/static/bidder-info/eplanning.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "producto@e-planning.net"
+gvlVendorID: 90
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/gamoshi.yaml b/static/bidder-info/gamoshi.yaml
index c3ed3ff1..0cfd4957 100644
--- a/static/bidder-info/gamoshi.yaml
+++ b/static/bidder-info/gamoshi.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "dev@gamoshi.com"
+gvlVendorID: 644
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/grid.yaml b/static/bidder-info/grid.yaml
index 325421a2..31c7b732 100644
--- a/static/bidder-info/grid.yaml
+++ b/static/bidder-info/grid.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "grid-tech@themediagrid.com"
+gvlVendorID: 686
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/gumgum.yaml b/static/bidder-info/gumgum.yaml
index 6ba563b4..bfefe63a 100644
--- a/static/bidder-info/gumgum.yaml
+++ b/static/bidder-info/gumgum.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@gumgum.com"
+gvlVendorID: 61
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/improvedigital.yaml b/static/bidder-info/improvedigital.yaml
index 7983cbc1..f7fea4a8 100644
--- a/static/bidder-info/improvedigital.yaml
+++ b/static/bidder-info/improvedigital.yaml
@@ -1,11 +1,14 @@
 maintainer:
   email: "hb@azerion.com"
+gvlVendorID: 253
 capabilities:
   app:
     mediaTypes:
       - banner
       - video
+      - native
   site:
     mediaTypes:
       - banner
       - video
+      - native
diff --git a/static/bidder-info/invibes.yaml b/static/bidder-info/invibes.yaml
index 14325297..45184fb9 100644
--- a/static/bidder-info/invibes.yaml
+++ b/static/bidder-info/invibes.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "system_operations@invibes.com"
+gvlVendorID: 436
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/ix.yaml b/static/bidder-info/ix.yaml
index 2f00ceb9..1e89c72e 100644
--- a/static/bidder-info/ix.yaml
+++ b/static/bidder-info/ix.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "pdu-supply-prebid@indexexchange.com"
+gvlVendorID: 10
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/lifestreet.yaml b/static/bidder-info/lifestreet.yaml
index 139d5599..34dc4eca 100644
--- a/static/bidder-info/lifestreet.yaml
+++ b/static/bidder-info/lifestreet.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "mobile.tech@lifestreet.com"
+gvlVendorID: 67
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/mediafuse.yaml b/static/bidder-info/mediafuse.yaml
index 112f67fe..98611402 100644
--- a/static/bidder-info/mediafuse.yaml
+++ b/static/bidder-info/mediafuse.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "support@mediafuse.com"
+gvlVendorID: 411
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/mgid.yaml b/static/bidder-info/mgid.yaml
index f8ba6db6..bddb8b85 100644
--- a/static/bidder-info/mgid.yaml
+++ b/static/bidder-info/mgid.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@mgid.com"
+gvlVendorID: 358
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/nanointeractive.yaml b/static/bidder-info/nanointeractive.yaml
index 244e7602..d199e9e8 100644
--- a/static/bidder-info/nanointeractive.yaml
+++ b/static/bidder-info/nanointeractive.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "development@nanointeractive.com"
+gvlVendorID: 72
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/nobid.yaml b/static/bidder-info/nobid.yaml
index 51a55de4..89f2a28a 100644
--- a/static/bidder-info/nobid.yaml
+++ b/static/bidder-info/nobid.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "developers@nobid.io"
+gvlVendorID: 816
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/onetag.yaml b/static/bidder-info/onetag.yaml
index fedaabf9..697ef04d 100644
--- a/static/bidder-info/onetag.yaml
+++ b/static/bidder-info/onetag.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: devops@onetag.com
+gvlVendorID: 241
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/openx.yaml b/static/bidder-info/openx.yaml
index 96ef8616..709f3db0 100644
--- a/static/bidder-info/openx.yaml
+++ b/static/bidder-info/openx.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@openx.com"
+gvlVendorID: 69
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/pubmatic.yaml b/static/bidder-info/pubmatic.yaml
index 4009d439..45c0418a 100644
--- a/static/bidder-info/pubmatic.yaml
+++ b/static/bidder-info/pubmatic.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "header-bidding@pubmatic.com"
+gvlVendorID: 76
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/pulsepoint.yaml b/static/bidder-info/pulsepoint.yaml
index 056a0bf3..bda03efd 100644
--- a/static/bidder-info/pulsepoint.yaml
+++ b/static/bidder-info/pulsepoint.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "ExchangeTeam@pulsepoint.com"
+gvlVendorID: 81
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/rhythmone.yaml b/static/bidder-info/rhythmone.yaml
index 89da6cfe..852344db 100644
--- a/static/bidder-info/rhythmone.yaml
+++ b/static/bidder-info/rhythmone.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "support@rhythmone.com"
+gvlVendorID: 36
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/rtbhouse.yaml b/static/bidder-info/rtbhouse.yaml
index f15af6ca..12744fdc 100644
--- a/static/bidder-info/rtbhouse.yaml
+++ b/static/bidder-info/rtbhouse.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@rtbhouse.com"
+gvlVendorID: 16
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/rubicon.yaml b/static/bidder-info/rubicon.yaml
index 40848e3e..0f19ddb9 100644
--- a/static/bidder-info/rubicon.yaml
+++ b/static/bidder-info/rubicon.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "header-bidding@rubiconproject.com"
+gvlVendorID: 52
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/sharethrough.yaml b/static/bidder-info/sharethrough.yaml
index 09530be5..45dceb94 100644
--- a/static/bidder-info/sharethrough.yaml
+++ b/static/bidder-info/sharethrough.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "pubgrowth.engineering@sharethrough.com"
+gvlVendorID: 80
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/smartadserver.yaml b/static/bidder-info/smartadserver.yaml
index 626b7dac..f22c7149 100644
--- a/static/bidder-info/smartadserver.yaml
+++ b/static/bidder-info/smartadserver.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "support@smartadserver.com"
+gvlVendorID: 45
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/somoaudience.yaml b/static/bidder-info/somoaudience.yaml
index 17156c18..83b64e5c 100644
--- a/static/bidder-info/somoaudience.yaml
+++ b/static/bidder-info/somoaudience.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "publishers@somoaudience.com"
+gvlVendorID: 341
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/sonobi.yaml b/static/bidder-info/sonobi.yaml
index 6d39319a..22a0a158 100644
--- a/static/bidder-info/sonobi.yaml
+++ b/static/bidder-info/sonobi.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "apex.prebid@sonobi.com"
+gvlVendorID: 104
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/sovrn.yaml b/static/bidder-info/sovrn.yaml
index c62d61df..4c6251bd 100644
--- a/static/bidder-info/sovrn.yaml
+++ b/static/bidder-info/sovrn.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "sovrnoss@sovrn.com"
+gvlVendorID: 13
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/tappx.yaml b/static/bidder-info/tappx.yaml
index 527959b7..eb655aa6 100644
--- a/static/bidder-info/tappx.yaml
+++ b/static/bidder-info/tappx.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "tappx@tappx.com"
+gvlVendorID: 628
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/telaria.yaml b/static/bidder-info/telaria.yaml
index 43e8707a..736fb972 100644
--- a/static/bidder-info/telaria.yaml
+++ b/static/bidder-info/telaria.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "github@telaria.com"
+gvlVendorID: 202
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/triplelift.yaml b/static/bidder-info/triplelift.yaml
index 2b9ff8d5..fe0ad8b2 100644
--- a/static/bidder-info/triplelift.yaml
+++ b/static/bidder-info/triplelift.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@triplelift.com"
+gvlVendorID: 28
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/triplelift_native.yaml b/static/bidder-info/triplelift_native.yaml
index abe91659..40d9be8f 100644
--- a/static/bidder-info/triplelift_native.yaml
+++ b/static/bidder-info/triplelift_native.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@triplelift.com"
+gvlVendorID: 28
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/trustx.yaml b/static/bidder-info/trustx.yaml
index 9ce52c11..6cfdd9fa 100644
--- a/static/bidder-info/trustx.yaml
+++ b/static/bidder-info/trustx.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "grid-tech@themediagrid.com"
+gvlVendorID: 686
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/ucfunnel.yaml b/static/bidder-info/ucfunnel.yaml
index 288b0b3f..e6be68a0 100644
--- a/static/bidder-info/ucfunnel.yaml
+++ b/static/bidder-info/ucfunnel.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "support@ucfunnel.com"
+gvlVendorID: 607
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/unruly.yaml b/static/bidder-info/unruly.yaml
index 01ed3774..e31ea600 100644
--- a/static/bidder-info/unruly.yaml
+++ b/static/bidder-info/unruly.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "adspaces@unrulygroup.com"
+gvlVendorID: 162
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/verizonmedia.yaml b/static/bidder-info/verizonmedia.yaml
index c00f2158..0b4642fc 100644
--- a/static/bidder-info/verizonmedia.yaml
+++ b/static/bidder-info/verizonmedia.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "dsp-supply-prebid@verizonmedia.com"
+gvlVendorID: 25
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/visx.yaml b/static/bidder-info/visx.yaml
index b6a16e4c..789ce478 100644
--- a/static/bidder-info/visx.yaml
+++ b/static/bidder-info/visx.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "supply.partners@yoc.com"
+gvlVendorID: 154
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/yieldlab.yaml b/static/bidder-info/yieldlab.yaml
index 654e6c74..3030d8a1 100644
--- a/static/bidder-info/yieldlab.yaml
+++ b/static/bidder-info/yieldlab.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "solutions@yieldlab.de"
+gvlVendorID: 70
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/yieldmo.yaml b/static/bidder-info/yieldmo.yaml
index 64cda519..b1385acb 100644
--- a/static/bidder-info/yieldmo.yaml
+++ b/static/bidder-info/yieldmo.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "prebid@yieldmo.com"
+gvlVendorID: 173
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-params/adyoulike.json b/static/bidder-params/adyoulike.json
new file mode 100644
index 00000000..448de344
--- /dev/null
+++ b/static/bidder-params/adyoulike.json
@@ -0,0 +1,33 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "AdYouLike Adapter Params",
+  "description": "A schema which validates params accepted by the AdYouLike adapter",
+  "type": "object",
+  "properties": {
+    "placement": {
+      "type": "string",
+      "description": "Placement Id"
+    },
+    "campaign": {
+      "type": "string",
+      "description": "Id of a forced campaign"
+    },
+    "track": {
+      "type": "string",
+      "description": "Id of a forced Track"
+    },
+    "creative": {
+      "type": "string",
+      "description": "Id of a forced creative"
+    },
+    "source": {
+      "type": "string",
+      "description": "context of the campaign"
+    },
+    "debug": {
+      "type": "string",
+      "description": "Arbitrary id used for debug purpose"
+    }
+  },
+  "required": ["placement"]
+}
diff --git a/usersync/usersync.go b/usersync/usersync.go
index 236acbe7..dffc1832 100644
--- a/usersync/usersync.go
+++ b/usersync/usersync.go
@@ -14,16 +14,6 @@ type Usersyncer interface {
 	// TODO #362: when the appnexus usersyncer is consistent, delete this and use the key
 	// of NewSyncerMap() here instead.
 	FamilyName() string
-
-	// GDPRVendorID returns the ID in the IAB Global Vendor List which refers to this Bidder.
-	//
-	// The Global Vendor list can be found here: https://vendor-list.consensu.org/vendorlist.json
-	// Bidders can register for the list here: https://register.consensu.org/
-	//
-	// If you're not on the list, this should return 0. If cookie sync requests have GDPR consent info,
-	// or the Prebid Server host company configures its deploy to be "cautious" when no GDPR info exists
-	// in the request, it will _not_ sync user IDs with you.
-	GDPRVendorID() uint16
 }
 
 type UsersyncInfo struct {
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
index 72159ad6..7467eb26 100644
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -17,6 +17,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/adtarget"
 	"github.com/prebid/prebid-server/adapters/adtelligent"
 	"github.com/prebid/prebid-server/adapters/advangelists"
+	"github.com/prebid/prebid-server/adapters/adyoulike"
 	"github.com/prebid/prebid-server/adapters/aja"
 	"github.com/prebid/prebid-server/adapters/amx"
 	"github.com/prebid/prebid-server/adapters/appnexus"
@@ -109,6 +110,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdtarget, adtarget.NewAdtargetSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdtelligent, adtelligent.NewAdtelligentSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdvangelists, advangelists.NewAdvangelistsSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdyoulike, adyoulike.NewAdyoulikeSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAJA, aja.NewAJASyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAMX, amx.NewAMXSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAppnexus, appnexus.NewAppnexusSyncer)


Test patch:
diff --git a/adapters/33across/usersync_test.go b/adapters/33across/usersync_test.go
index a9eb4e57..e99b5965 100644
--- a/adapters/33across/usersync_test.go
+++ b/adapters/33across/usersync_test.go
@@ -30,6 +30,5 @@ func Test33AcrossSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ic.tynt.com/r/d?m=xch&rt=html&gdpr=A&gdpr_consent=B&us_privacy=C&ru=%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 58, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/acuityads/usersync_test.go b/adapters/acuityads/usersync_test.go
index 1f57cea3..b3ad10bd 100644
--- a/adapters/acuityads/usersync_test.go
+++ b/adapters/acuityads/usersync_test.go
@@ -29,6 +29,5 @@ func TestAcuityAdsSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://cs.admanmedia.com/sync/prebid?gdpr=0&gdpr_consent=ANDFJDS&us_privacy=1-YY&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dacuityads%26uid%3D%5BUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 231, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adapterstest/test_json.go b/adapters/adapterstest/test_json.go
index a25a4f19..1e3178ed 100644
--- a/adapters/adapterstest/test_json.go
+++ b/adapters/adapterstest/test_json.go
@@ -123,7 +123,7 @@ func runSpec(t *testing.T, filename string, spec *testSpec, bidder adapters.Bidd
 	diffErrorLists(t, fmt.Sprintf("%s: MakeBids", filename), bidsErrs, spec.MakeBidsErrors)
 
 	for i := 0; i < len(spec.BidResponses); i++ {
-		diffBidLists(t, filename, bidResponses[i].Bids, spec.BidResponses[i].Bids)
+		diffBidLists(t, filename, bidResponses[i], spec.BidResponses[i].Bids)
 	}
 }
 
@@ -227,9 +227,24 @@ func diffErrorLists(t *testing.T, description string, actual []error, expected [
 	}
 }
 
-func diffBidLists(t *testing.T, filename string, actual []*adapters.TypedBid, expected []expectedBid) {
+func diffBidLists(t *testing.T, filename string, response *adapters.BidderResponse, expected []expectedBid) {
 	t.Helper()
 
+	if (response == nil || len(response.Bids) == 0) != (len(expected) == 0) {
+		if len(expected) == 0 {
+			t.Fatalf("%s: expectedBidResponses indicated a nil response, but mockResponses supplied a non-nil response", filename)
+		}
+
+		t.Fatalf("%s: mockResponses included unexpected nil or empty response", filename)
+	}
+
+	// Expected nil response - give diffBids something to work with.
+	if response == nil {
+		response = new(adapters.BidderResponse)
+	}
+
+	actual := response.Bids
+
 	if len(actual) != len(expected) {
 		t.Fatalf("%s: MakeBids returned wrong bid count. Expected %d, got %d", filename, len(expected), len(actual))
 	}
diff --git a/adapters/adform/usersync_test.go b/adapters/adform/usersync_test.go
index 855506da..f133be86 100644
--- a/adapters/adform/usersync_test.go
+++ b/adapters/adform/usersync_test.go
@@ -27,6 +27,5 @@ func TestAdformSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//cm.adform.net?return_url=localhost%2Fsetuid%3Fbidder%3Dadform%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 50, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adkernel/usersync_test.go b/adapters/adkernel/usersync_test.go
index aeacf00b..2ff81668 100644
--- a/adapters/adkernel/usersync_test.go
+++ b/adapters/adkernel/usersync_test.go
@@ -30,6 +30,5 @@ func TestAdkernelAdnSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://sync.adkernel.com/user-sync?t=image&gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%7BUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, adkernelGDPRVendorID, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adkernelAdn/usersync_test.go b/adapters/adkernelAdn/usersync_test.go
index 92d688e6..17cf97ce 100644
--- a/adapters/adkernelAdn/usersync_test.go
+++ b/adapters/adkernelAdn/usersync_test.go
@@ -30,6 +30,5 @@ func TestAdkernelAdnSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://tag.adkernel.com/syncr?gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3DadkernelAdn%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%7BUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, adkernelGDPRVendorID, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adman/usersync_test.go b/adapters/adman/usersync_test.go
index 25da77db..d0dc90c8 100644
--- a/adapters/adman/usersync_test.go
+++ b/adapters/adman/usersync_test.go
@@ -30,6 +30,5 @@ func TestAdmanSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://sync.admanmedia.com/pbs.gif?gdpr=0&gdpr_consent=ANDFJDS&us_privacy=1-YY&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dadman%26uid%3D%5BUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 149, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/admixer/usersync_test.go b/adapters/admixer/usersync_test.go
index 79f023a2..6acc4845 100644
--- a/adapters/admixer/usersync_test.go
+++ b/adapters/admixer/usersync_test.go
@@ -30,6 +30,6 @@ func TestAdmixerSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "http://anyHost/anyPath", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 511, syncer.GDPRVendorID())
+
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adocean/usersync_test.go b/adapters/adocean/usersync_test.go
index 9ca81b98..5257017a 100644
--- a/adapters/adocean/usersync_test.go
+++ b/adapters/adocean/usersync_test.go
@@ -30,5 +30,4 @@ func TestAdOceanSyncer(t *testing.T) {
 		syncInfo.URL,
 	)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 328, syncer.GDPRVendorID())
 }
diff --git a/adapters/adpone/usersync_test.go b/adapters/adpone/usersync_test.go
index 87b4e9ae..e744de5e 100644
--- a/adapters/adpone/usersync_test.go
+++ b/adapters/adpone/usersync_test.go
@@ -20,5 +20,4 @@ func TestAdponeSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://usersync.adpone.com/csync?t=p&ep=0&redir=localhost%2Fsetuid%3Fbidder%3Dadtelligent%26gdpr%3D%26gdpr_consent%3D%26uid%3D%7Buid%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, adponeGDPRVendorID, syncer.GDPRVendorID())
 }
diff --git a/adapters/adtarget/usersync_test.go b/adapters/adtarget/usersync_test.go
index ddba9e7a..ea6146ce 100644
--- a/adapters/adtarget/usersync_test.go
+++ b/adapters/adtarget/usersync_test.go
@@ -33,6 +33,5 @@ func TestAdtargetSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//sync.console.adtarget.com.tr/csync?t=p&ep=0&gdpr=0&gdpr_consent=123&us_privacy=1-YY&redir=localhost%2Fsetuid%3Fbidder%3Dadtarget%26gdpr%3D0%26gdpr_consent%3D123%26uid%3D%7Buid%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adtelligent/usersync_test.go b/adapters/adtelligent/usersync_test.go
index fa157d22..2430f377 100644
--- a/adapters/adtelligent/usersync_test.go
+++ b/adapters/adtelligent/usersync_test.go
@@ -25,6 +25,5 @@ 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, 410, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/advangelists/usersync_test.go b/adapters/advangelists/usersync_test.go
index 2167d49f..04ee7968 100644
--- a/adapters/advangelists/usersync_test.go
+++ b/adapters/advangelists/usersync_test.go
@@ -26,6 +26,5 @@ func TestAdvangelistsSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://nep.advangelists.com/xp/user-sync?acctid={aid}&&redirect=localhost/setuid?bidder=advangelists&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&uid=$UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/adyoulike/adyoulike_test.go b/adapters/adyoulike/adyoulike_test.go
new file mode 100644
index 00000000..9ab689f3
--- /dev/null
+++ b/adapters/adyoulike/adyoulike_test.go
@@ -0,0 +1,22 @@
+package adyoulike
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+const testsBidderEndpoint = "https://localhost/bid/4"
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderAdyoulike, config.Adapter{
+		Endpoint: testsBidderEndpoint})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "adyouliketest", bidder)
+}
diff --git a/adapters/adyoulike/adyouliketest/exemplary/multiformat-impression.json b/adapters/adyoulike/adyouliketest/exemplary/multiformat-impression.json
new file mode 100644
index 00000000..2ae99c04
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/exemplary/multiformat-impression.json
@@ -0,0 +1,169 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        },
+        {
+          "id": "video-imp-id",
+          "video": {
+            "w": 640,
+            "h": 480
+          },
+          "ext": {
+            "bidder": {
+              "placement": "54321"
+            }
+          }
+        },
+        {
+          "id": "native-imp-id",
+          "native": {
+            "title": "required"
+          },
+          "ext": {
+            "bidder": {
+              "placement": "123123"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "https://localhost/bid/4",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "ext": {
+                  "bidder": {
+                    "placement": "12345"
+                  }
+                },
+                "id": "banner-imp-id",
+                "tagid": "12345"
+              },
+              {
+                "ext": {
+                  "bidder": {
+                    "placement": "54321"
+                  }
+                },
+                "id": "video-imp-id",
+                "tagid": "54321",
+                "video": {
+                  "h": 480,
+                  "mimes": null,
+                  "w": 640
+                }
+              },
+              {
+                "ext": {
+                  "bidder": {
+                    "placement": "123123"
+                  }
+                },
+                "id": "native-imp-id",
+                "native": {
+                  "request": ""
+                },
+                "tagid": "123123"
+              }
+            ]
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "test-response-id",
+            "seatbid": [{
+              "seat": "1",
+              "bid": [{
+                  "id":    "12340",
+                  "impid": "banner-imp-id",
+                  "price": 300,
+                  "adm": "%3C%3Fxml%20version%3D%221.0%22%20encod%2Fhtml%3E",
+                  "nurl": "http://example.com/winnoticeurl0"
+                },
+                {
+                  "id":    "12341",
+                  "impid": "video-imp-id",
+                  "price": 301,
+                  "adm": "%3C%3Fxml%20version%3D%221.0%22%20encod%2FVAST%3E",
+                  "nurl": "http://example.com/winnoticeurl1"
+                },
+                {                  
+                  "id":    "12342",
+                  "impid": "native-imp-id",
+                  "price": 302,
+                  "adm": "{'json':'response','for':'native'}",
+                  "nurl": "http://example.com/winnoticeurl2"
+                }
+              ]
+            }]
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [
+      {
+        "currency": "USD",
+        "bids": [
+          {
+            "bid": {
+              "id":    "12340",
+              "impid": "banner-imp-id",
+              "price": 300,
+              "nurl":  "http://example.com/winnoticeurl0",
+              "adm":   "%3C%3Fxml%20version%3D%221.0%22%20encod%2Fhtml%3E"
+            },
+            "type": "banner"
+          },
+          {
+            "bid": {
+              "id":    "12341",
+              "impid": "video-imp-id",
+              "price": 301,
+              "nurl":  "http://example.com/winnoticeurl1",
+              "adm":   "%3C%3Fxml%20version%3D%221.0%22%20encod%2FVAST%3E"
+            },
+            "type": "video"
+          },
+          {
+            "bid": {
+              "id":    "12342",
+              "impid": "native-imp-id",
+              "price": 302,
+              "nurl":  "http://example.com/winnoticeurl2",
+              "adm":   "{'json':'response','for':'native'}"
+            },
+            "type": "native"
+          }
+        ]
+      }
+    ]
+  }
diff --git a/adapters/adyoulike/adyouliketest/params/race/banner.json b/adapters/adyoulike/adyouliketest/params/race/banner.json
new file mode 100644
index 00000000..726ca878
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/params/race/banner.json
@@ -0,0 +1,3 @@
+{
+  "placement": "19f1b372c7548ec1fe734d2c9f8dc688"
+}
diff --git a/adapters/adyoulike/adyouliketest/params/race/video.json b/adapters/adyoulike/adyouliketest/params/race/video.json
new file mode 100644
index 00000000..d0883f5e
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/params/race/video.json
@@ -0,0 +1,3 @@
+{
+    "placement": "19f1b372c7548ec1fe734d2c9f8dc688"
+}
diff --git a/adapters/adyoulike/adyouliketest/supplemental/invalid-bid-response.json b/adapters/adyoulike/adyouliketest/supplemental/invalid-bid-response.json
new file mode 100644
index 00000000..b156dd65
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/supplemental/invalid-bid-response.json
@@ -0,0 +1,65 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "https://localhost/bid/4",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "ext": {
+                  "bidder": {
+                    "placement": "12345"
+                  }
+                },
+                "id": "banner-imp-id",
+                "tagid": "12345"
+              }
+            ]
+          }
+        },
+      "mockResponse": {
+        "status": 200,
+        "body": ""
+      }
+    }
+  ],
+
+  "expectedBidResponses": [],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "json: cannot unmarshal string into Go value of type openrtb.BidResponse",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/adyoulike/adyouliketest/supplemental/status-bad-request.json b/adapters/adyoulike/adyouliketest/supplemental/status-bad-request.json
new file mode 100644
index 00000000..83b5f361
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/supplemental/status-bad-request.json
@@ -0,0 +1,66 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "https://localhost/bid/4",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "ext": {
+                  "bidder": {
+                    "placement": "12345"
+                  }
+                },
+                "id": "banner-imp-id",
+                "tagid": "12345"
+              }
+            ]
+          }
+        },
+      "mockResponse": {
+        "status": 400,
+        "body": {
+        }
+      }
+    }
+  ],
+
+  "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/adyoulike/adyouliketest/supplemental/status-no-content.json b/adapters/adyoulike/adyouliketest/supplemental/status-no-content.json
new file mode 100644
index 00000000..9ef51e88
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/supplemental/status-no-content.json
@@ -0,0 +1,66 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "https://localhost/bid/4",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "ext": {
+                  "bidder": {
+                    "placement": "12345"
+                  }
+                },
+                "id": "banner-imp-id",
+                "tagid": "12345"
+              }
+            ]
+          }
+        },
+      "mockResponse": {
+        "status": 204,
+        "body": {
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "MakeBids error: No Content",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/adyoulike/adyouliketest/supplemental/status-service-unavailable.json b/adapters/adyoulike/adyouliketest/supplemental/status-service-unavailable.json
new file mode 100644
index 00000000..2b5872a1
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/supplemental/status-service-unavailable.json
@@ -0,0 +1,66 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "https://localhost/bid/4",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "ext": {
+                  "bidder": {
+                    "placement": "12345"
+                  }
+                },
+                "id": "banner-imp-id",
+                "tagid": "12345"
+              }
+            ]
+          }
+        },
+      "mockResponse": {
+        "status": 503,
+        "body": {
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 503. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/adyoulike/adyouliketest/supplemental/status-unknown.json b/adapters/adyoulike/adyouliketest/supplemental/status-unknown.json
new file mode 100644
index 00000000..0b9ce745
--- /dev/null
+++ b/adapters/adyoulike/adyouliketest/supplemental/status-unknown.json
@@ -0,0 +1,66 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "banner-imp-id",
+          "banner": {
+            "format": [
+              {
+                "w": 300,
+                "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "placement": "12345"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "https://localhost/bid/4",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "banner": {
+                  "format": [
+                    {
+                      "h": 250,
+                      "w": 300
+                    }
+                  ]
+                },
+                "ext": {
+                  "bidder": {
+                    "placement": "12345"
+                  }
+                },
+                "id": "banner-imp-id",
+                "tagid": "12345"
+              }
+            ]
+          }
+        },
+      "mockResponse": {
+        "status": 999,
+        "body": {
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 999. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/adyoulike/params_test.go b/adapters/adyoulike/params_test.go
new file mode 100644
index 00000000..b57264b3
--- /dev/null
+++ b/adapters/adyoulike/params_test.go
@@ -0,0 +1,62 @@
+package adyoulike
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// This file actually intends to test static/bidder-params/adyoulike.json
+//
+// These also validate the format of the external API: request.imp[i].ext.adyoulike
+
+// TestValidParams makes sure that the adyoulike 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.BidderAdyoulike, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected adyoulike params: %s", validParam)
+		}
+	}
+}
+
+// TestInvalidParams makes sure that the adyoulike 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.BidderAdyoulike, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"placement":"123"}`,
+	`{"placement":"123","campaign":"456"}`,
+	`{"placement":"123","campaign":"456","track":"789"}`,
+	`{"placement":"123","campaign":"456","track":"789","creative":"ABC"}`,
+	`{"placement":"123","campaign":"456","track":"789","creative":"ABC","source":"SSP"}`,
+	`{"placement":"123","campaign":"456","track":"789","creative":"ABC","source":"SSP","debug":"info"}`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"invalid":"123"}`,
+	`{"placement":123}`,
+	`{"placement":"123","campaign":123}`,
+}
diff --git a/adapters/adyoulike/usersync_test.go b/adapters/adyoulike/usersync_test.go
new file mode 100644
index 00000000..72def4cf
--- /dev/null
+++ b/adapters/adyoulike/usersync_test.go
@@ -0,0 +1,35 @@
+package adyoulike
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/ccpa"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+)
+
+func TestAdyoulikeSyncer(t *testing.T) {
+	syncURL := "//visitor.omnitagjs.com/visitor/bsync?uid=19340f4f097d16f41f34fc0274981ca4&name=PrebidServer&gdpr_consent_string={{.GDPRConsent}}&gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewAdyoulikeSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "1",
+			Consent: "BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw",
+		},
+		CCPA: ccpa.Policy{
+			Consent: "1-YY",
+		},
+	})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "//visitor.omnitagjs.com/visitor/bsync?uid=19340f4f097d16f41f34fc0274981ca4&name=PrebidServer&gdpr_consent_string=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&gdpr=1&us_privacy=1-YY", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/adapters/aja/usersync_test.go b/adapters/aja/usersync_test.go
index 4b6c90ef..dabd5e19 100644
--- a/adapters/aja/usersync_test.go
+++ b/adapters/aja/usersync_test.go
@@ -31,6 +31,5 @@ func TestAJASyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr=1&us_privacy=C&redir=localhost/setuid?bidder=aja&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&uid=%s", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/amx/usersync_test.go b/adapters/amx/usersync_test.go
index 20a47c33..b6b6e6ba 100644
--- a/adapters/amx/usersync_test.go
+++ b/adapters/amx/usersync_test.go
@@ -18,6 +18,5 @@ func TestAMXSyncer(t *testing.T) {
 	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/appnexus/usersync_test.go b/adapters/appnexus/usersync_test.go
index 24b9eede..d01e5704 100644
--- a/adapters/appnexus/usersync_test.go
+++ b/adapters/appnexus/usersync_test.go
@@ -20,6 +20,5 @@ func TestAppNexusSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ib.adnxs.com/getuid?https%3A%2F%2Fprebid.adnxs.com%2Fpbs%2Fv1%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 32, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/audienceNetwork/usersync_test.go b/adapters/audienceNetwork/usersync_test.go
index c3836e4f..591ea74f 100644
--- a/adapters/audienceNetwork/usersync_test.go
+++ b/adapters/audienceNetwork/usersync_test.go
@@ -20,6 +20,5 @@ func TestFacebookSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://www.facebook.com/audiencenetwork/idsync/?partner=partnerId&callback=localhost%2Fsetuid%3Fbidder%3DaudienceNetwork%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/avocet/usersync_test.go b/adapters/avocet/usersync_test.go
index 3df39b77..bd4cd414 100644
--- a/adapters/avocet/usersync_test.go
+++ b/adapters/avocet/usersync_test.go
@@ -30,6 +30,5 @@ func TestAvocetSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ads.avct.cloud/getuid?&gdpr=1&gdpr_consent=ConsentString&us_privacy=PrivacyString&url=%2Fsetuid%3Fbidder%3Davocet%26gdpr%3D1%26gdpr_consent%3DConsentString%26uid%3D%7B%7BUUID%7D%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 63, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/beachfront/beachfronttest/exemplary/adm-video.json b/adapters/beachfront/beachfronttest/exemplary/adm-video.json
index 26b050f2..edde1301 100644
--- a/adapters/beachfront/beachfronttest/exemplary/adm-video.json
+++ b/adapters/beachfront/beachfronttest/exemplary/adm-video.json
@@ -96,6 +96,7 @@
 
   "expectedBidResponses": [
     {
+      "currency": "USD",
       "bids": [
         {
           "bid": {
diff --git a/adapters/beachfront/beachfronttest/exemplary/banner.json b/adapters/beachfront/beachfronttest/exemplary/banner.json
index e3dcffa3..1a8e8305 100644
--- a/adapters/beachfront/beachfronttest/exemplary/banner.json
+++ b/adapters/beachfront/beachfronttest/exemplary/banner.json
@@ -45,6 +45,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-204-with-body.json b/adapters/beachfront/beachfronttest/supplemental/banner-204-with-body.json
new file mode 100644
index 00000000..edba490e
--- /dev/null
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-204-with-body.json
@@ -0,0 +1,79 @@
+{
+  "mockBidRequest": {
+    "id": "some_test_ad",
+    "site": {
+      "page": "https://some.domain.us/some/page.html"
+    },
+    "imp": [
+      {
+        "id": "dudImp",
+        "bidfloor": 0.02,
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "bidfloor": 0.02,
+            "appId": "dudAppId1"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://qa.beachrtb.com/prebid_display",
+        "body": {
+          "slots": [
+            {
+              "slot": "dudImp",
+              "id": "dudAppId1",
+              "bidfloor": 0.02,
+              "sizes": [
+                {
+                  "w": 300,
+                  "h": 250
+                }
+              ]
+            }
+          ],
+          "domain": "some.domain.us",
+          "page": "https://some.domain.us/some/page.html",
+          "real204": true,
+          "referrer": "",
+          "search": "",
+          "secure": 1,
+          "requestId": "some_test_ad",
+          "isMobile": 0,
+          "ip": "",
+          "deviceModel": "",
+          "deviceOs": "",
+          "dnt": 0,
+          "ua": "",
+          "adapterName": "BF_PREBID_S2S",
+          "adapterVersion": "0.9.2",
+          "user": {
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": [
+          {
+            "something": "where nothing should be"
+          }
+        ]
+      }
+    }
+  ],
+
+  "expectedBidResponses": []
+}
+
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-empty_array-200.json b/adapters/beachfront/beachfronttest/supplemental/banner-204.json
similarity index 81%
rename from adapters/beachfront/beachfronttest/supplemental/banner-empty_array-200.json
rename to adapters/beachfront/beachfronttest/supplemental/banner-204.json
index 8e607f67..69aa0b88 100644
--- a/adapters/beachfront/beachfronttest/supplemental/banner-empty_array-200.json
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-204.json
@@ -46,6 +46,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
@@ -63,18 +64,13 @@
         }
       },
       "mockResponse": {
-        "status": 200,
-        "body": []
+        "status": 204,
+        "body": ""
       }
     }
   ],
 
-  "expectedBidResponses": [],
+  "expectedBidResponses": [
 
-  "expectedMakeBidsErrors": [
-    {
-      "value": "no content or truncated content received from server. status code 200 from https://qa.beachrtb.com/prebid_display. Run with request.debug = 1 for more info",
-      "comparison": "literal"
-    }
   ]
 }
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-by-explicit.json b/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-by-explicit.json
index c326a33a..b060efe6 100644
--- a/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-by-explicit.json
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-by-explicit.json
@@ -60,6 +60,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-expected-204-response-on-banner.json b/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-expected-204-response-on-banner.json
new file mode 100644
index 00000000..240994bb
--- /dev/null
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video-expected-204-response-on-banner.json
@@ -0,0 +1,171 @@
+{
+  "mockBidRequest": {
+    "id": "banner-and-video",
+    "imp": [
+      {
+        "id": "mix1",
+        "ext": {
+          "bidder": {
+            "bidfloor": 0.41,
+            "appIds": {
+              "banner": "bannerAppId1",
+              "video": "videoAppId1"
+            }
+          }
+        },
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "context": "instream",
+          "w": 300,
+          "h": 250
+        },
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        }
+      }
+    ],
+    "site": {
+      "page": "https://some.domain.us/some/page.html"
+    },
+    "device":{
+      "ip":"255.255.255.255"
+    }
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://qa.beachrtb.com/prebid_display",
+        "body": {
+          "slots": [
+            {
+              "slot": "mix1",
+              "id": "bannerAppId1",
+              "bidfloor": 0.41,
+              "sizes": [
+                {
+                  "w": 300,
+                  "h": 250
+                }
+              ]
+            }
+          ],
+          "domain": "some.domain.us",
+          "page": "https://some.domain.us/some/page.html",
+          "real204": true,
+          "referrer": "",
+          "search": "",
+          "secure": 1,
+          "deviceOs": "",
+          "deviceModel": "",
+          "isMobile": 0,
+          "ua": "",
+          "ip": "255.255.255.255",
+          "dnt": 0,
+          "user": {},
+          "adapterName": "BF_PREBID_S2S",
+          "adapterVersion": "0.9.2",
+          "requestId": "banner-and-video"
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": ""
+      }
+    },
+    {
+      "expectedRequest": {
+        "uri": "https://qa.beachrtb.com/bid.json?exchange_id=videoAppId1",
+        "body": {
+          "id": "banner-and-video",
+          "imp": [
+            {
+              "video": {
+                "w": 300,
+                "h": 250,
+                "mimes": [
+                  "video/mp4"
+                ]
+              },
+              "bidfloor": 0.41,
+              "secure": 1,
+              "id": "mix1"
+            }
+          ],
+          "site": {
+            "domain": "some.domain.us",
+            "page": "https://some.domain.us/some/page.html"
+          },
+          "device": {
+            "devicetype": 2,
+            "ip": "255.255.255.255"
+          },
+          "cur": [
+            "USD"
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "61b87329-8790-47b7-90dd-c53ae7ce1723",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "5d839458f73decdc1572b7f6",
+                  "impid": "mix1",
+                  "price": 20,
+                  "adm": "<VAST version=\"2.0\"><Ad><Wrapper>http://example.com/vast.xml</Wrapper></Ad></VAST>",
+                  "adid": "1088",
+                  "adomain": [
+                    "beachfront.io"
+                  ],
+                  "cid": "277",
+                  "crid": "532",
+                  "w": 300,
+                  "h": 250
+                }
+              ],
+              "seat": "bfb-io-s1"
+            }
+          ],
+          "bidid": "5d839458f73decdc1572b7f6",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {"bids":[]},
+    {
+      "bids": [
+        {
+          "bid": {
+            "id": "mix1AdmVideo",
+            "impid": "mix1",
+            "price": 20,
+            "adm": "<VAST version=\"2.0\"><Ad><Wrapper>http://example.com/vast.xml</Wrapper></Ad></VAST>",
+            "adid": "1088",
+            "adomain": [
+              "beachfront.io"
+            ],
+            "cid": "277",
+            "crid": "532",
+            "w": 300,
+            "h": 250
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video.json b/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video.json
index f67903d0..18e8ca7a 100644
--- a/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video.json
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-and-adm-video.json
@@ -59,6 +59,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-and-nurl-video.json b/adapters/beachfront/beachfronttest/supplemental/banner-and-nurl-video.json
index b950d734..2ef8ca58 100644
--- a/adapters/beachfront/beachfronttest/supplemental/banner-and-nurl-video.json
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-and-nurl-video.json
@@ -57,6 +57,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/banner-bad-request-400.json b/adapters/beachfront/beachfronttest/supplemental/banner-bad-request-400.json
index 1771f393..35926b3c 100644
--- a/adapters/beachfront/beachfronttest/supplemental/banner-bad-request-400.json
+++ b/adapters/beachfront/beachfronttest/supplemental/banner-bad-request-400.json
@@ -45,6 +45,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/bidder_response_unmarshal_error_banner.json b/adapters/beachfront/beachfronttest/supplemental/bidder_response_unmarshal_error_banner.json
index b751f763..e7869d36 100644
--- a/adapters/beachfront/beachfronttest/supplemental/bidder_response_unmarshal_error_banner.json
+++ b/adapters/beachfront/beachfronttest/supplemental/bidder_response_unmarshal_error_banner.json
@@ -44,6 +44,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/bidfloor-below-min.json b/adapters/beachfront/beachfronttest/supplemental/bidfloor-below-min.json
index f5d4e822..7ebe6cf4 100644
--- a/adapters/beachfront/beachfronttest/supplemental/bidfloor-below-min.json
+++ b/adapters/beachfront/beachfronttest/supplemental/bidfloor-below-min.json
@@ -44,6 +44,7 @@
           ],
           "domain": "some.domain.us",
           "page": "https://some.domain.us/some/page.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 1,
diff --git a/adapters/beachfront/beachfronttest/supplemental/six-nine-combo.json b/adapters/beachfront/beachfronttest/supplemental/six-nine-combo.json
index 4c009ff0..9a8ca734 100644
--- a/adapters/beachfront/beachfronttest/supplemental/six-nine-combo.json
+++ b/adapters/beachfront/beachfronttest/supplemental/six-nine-combo.json
@@ -189,6 +189,7 @@
           ],
           "domain": "example.com",
           "page": "http://example.com/whatever/something.html",
+          "real204": true,
           "referrer": "",
           "search": "",
           "secure": 0,
diff --git a/adapters/beachfront/beachfronttest/supplemental/two-four-combo.json b/adapters/beachfront/beachfronttest/supplemental/two-four-combo.json
index d48962e6..ac1ca19f 100644
--- a/adapters/beachfront/beachfronttest/supplemental/two-four-combo.json
+++ b/adapters/beachfront/beachfronttest/supplemental/two-four-combo.json
@@ -97,6 +97,7 @@
           ],
           "domain":"example.com",
           "page":"http://example.com/whatever/something.html",
+          "real204": true,
           "referrer":"",
           "search":"",
           "secure":0,
diff --git a/adapters/beachfront/usersync_test.go b/adapters/beachfront/usersync_test.go
index db4d825e..edb52bd4 100644
--- a/adapters/beachfront/usersync_test.go
+++ b/adapters/beachfront/usersync_test.go
@@ -30,6 +30,5 @@ func TestBeachfrontSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://sync.bfmio.com/sync_s2s?gdpr=A&us_privacy=C&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%5Bio_cid%5D", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, uint16(335), syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/beintoo/usersync_test.go b/adapters/beintoo/usersync_test.go
index 880d6a84..65d92e6d 100644
--- a/adapters/beintoo/usersync_test.go
+++ b/adapters/beintoo/usersync_test.go
@@ -30,6 +30,5 @@ func TestBeintooSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ib.beintoo.com/um?ssp=pbs&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redirect=localhost%2Fsetuid%3Fbidder%3Dbeintoo%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 618, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/between/usersync_test.go b/adapters/between/usersync_test.go
index 6470a9c4..c54f473b 100644
--- a/adapters/between/usersync_test.go
+++ b/adapters/between/usersync_test.go
@@ -1,10 +1,11 @@
 package between
 
 import (
-	"github.com/prebid/prebid-server/privacy"
-	"github.com/stretchr/testify/assert"
 	"testing"
 	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestNewBetweenSyncerSyncer(t *testing.T) {
@@ -19,6 +20,5 @@ func TestNewBetweenSyncerSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ads.betweendigital.com/match?bidder_id=pbs&gdpr=&gdpr_consent=&us_privacy=&callback_url=localhost:8080%2Fsetuid%3Fbidder%3Dbetween%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24%7BUSER_ID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 724, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/brightroll/usersync_test.go b/adapters/brightroll/usersync_test.go
index a5d47e35..fac17b0a 100644
--- a/adapters/brightroll/usersync_test.go
+++ b/adapters/brightroll/usersync_test.go
@@ -20,6 +20,5 @@ func TestBrightrollSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "http://test-bh.ybp.yahoo.com/sync/appnexuspbs?gdpr=&euconsent=&us_privacy=&url=localhost%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 25, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/colossus/usersync_test.go b/adapters/colossus/usersync_test.go
index 52eb6389..4cb3a4bb 100644
--- a/adapters/colossus/usersync_test.go
+++ b/adapters/colossus/usersync_test.go
@@ -30,6 +30,5 @@ func TestColossusSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://sync.colossusssp.com/pbs.gif?gdpr=0&gdpr_consent=A&us_privacy=1-YY&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dcolossus%26uid%3D%5BUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/connectad/usersync_test.go b/adapters/connectad/usersync_test.go
index c4b4962b..81b0dc47 100644
--- a/adapters/connectad/usersync_test.go
+++ b/adapters/connectad/usersync_test.go
@@ -30,6 +30,5 @@ func TestConnectAdSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://cdn.connectad.io/connectmyusers.php?gdpr=1&consent=fakeconsent&us_privacy=fake&cb=localhost%2Fsetuid%3Fbidder%3Dconnectad%26gdpr%3D1%26gdpr_consent%3Dfakeconsent%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 138, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/consumable/usersync_test.go b/adapters/consumable/usersync_test.go
index ef71c0b1..0af868a0 100644
--- a/adapters/consumable/usersync_test.go
+++ b/adapters/consumable/usersync_test.go
@@ -30,6 +30,5 @@ func TestConsumableSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//e.serverbid.com/udb/9969/match?gdpr=A&euconsent=B&us_privacy=C&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dconsumable%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D", u.URL)
 	assert.Equal(t, "redirect", u.Type)
-	assert.Equal(t, uint16(591), syncer.GDPRVendorID())
 	assert.Equal(t, false, u.SupportCORS)
 }
diff --git a/adapters/conversant/usersync_test.go b/adapters/conversant/usersync_test.go
index 16affbd1..62ab732c 100644
--- a/adapters/conversant/usersync_test.go
+++ b/adapters/conversant/usersync_test.go
@@ -25,6 +25,5 @@ func TestConversantSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "usersync?rurl=localhost%2Fsetuid%3Fbidder%3Dconversant%26gdpr%3D0%26gdpr_consent%3D%26uid%3D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 24, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/cpmstar/usersync_test.go b/adapters/cpmstar/usersync_test.go
index dae55e63..9bae7062 100644
--- a/adapters/cpmstar/usersync_test.go
+++ b/adapters/cpmstar/usersync_test.go
@@ -20,6 +20,5 @@ func TestCpmstarSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://server.cpmstar.com/usersync.aspx?gdpr=&gdpr_consent=&us_privacy=&redirectUri=http%3A%2F%2Flocalhost:8000%2Fsetuid%3Fbidder%3Dcpmstar%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/datablocks/usersync_test.go b/adapters/datablocks/usersync_test.go
index a7518e9b..d6ee5804 100644
--- a/adapters/datablocks/usersync_test.go
+++ b/adapters/datablocks/usersync_test.go
@@ -30,6 +30,5 @@ func TestDatablocksSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&r=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%24%7Buid%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, datablocksGDPRVendorID, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/deepintent/usersync_test.go b/adapters/deepintent/usersync_test.go
index 06a221ca..6709a838 100644
--- a/adapters/deepintent/usersync_test.go
+++ b/adapters/deepintent/usersync_test.go
@@ -30,6 +30,5 @@ func TestDeepintentSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://match.deepintent.com/usersync/136?id=unk&gdpr=A&us_privacy=C&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%5Bio_cid%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, uint16(541), syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/dmx/usersync_test.go b/adapters/dmx/usersync_test.go
index e4e3c7d8..a316af04 100644
--- a/adapters/dmx/usersync_test.go
+++ b/adapters/dmx/usersync_test.go
@@ -1,10 +1,11 @@
 package dmx
 
 import (
-	"github.com/prebid/prebid-server/privacy"
 	"testing"
 	"text/template"
 
+	"github.com/prebid/prebid-server/privacy"
+
 	"github.com/stretchr/testify/assert"
 )
 
@@ -15,6 +16,5 @@ func TestDmxSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://dmx.districtm.io/s/v1/img/s/10007", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 144, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/emx_digital/usersync_test.go b/adapters/emx_digital/usersync_test.go
index 59d66d87..7aaf1335 100644
--- a/adapters/emx_digital/usersync_test.go
+++ b/adapters/emx_digital/usersync_test.go
@@ -30,6 +30,5 @@ func TestEMXDigitalSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://cs.emxdgt.com/um?ssp=pbs&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redirect=localhost%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 183, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/engagebdr/usersync_test.go b/adapters/engagebdr/usersync_test.go
index 3a6c179a..5cee3abe 100644
--- a/adapters/engagebdr/usersync_test.go
+++ b/adapters/engagebdr/usersync_test.go
@@ -30,6 +30,5 @@ func TestEngageBDRSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://match.bnmla.com/usersync/s2s?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&r=localhost%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 62, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/eplanning/usersync_test.go b/adapters/eplanning/usersync_test.go
index 85770689..922ab4e2 100644
--- a/adapters/eplanning/usersync_test.go
+++ b/adapters/eplanning/usersync_test.go
@@ -20,6 +20,5 @@ 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, 90, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/gamma/usersync_test.go b/adapters/gamma/usersync_test.go
index 4278f9ab..7636e05a 100644
--- a/adapters/gamma/usersync_test.go
+++ b/adapters/gamma/usersync_test.go
@@ -25,6 +25,5 @@ func TestGammaSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//hb.gammaplatform.com/sync?gdpr=0&gdpr_consent=&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dgamma%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/gamoshi/usersync_test.go b/adapters/gamoshi/usersync_test.go
index 43dc88a4..0465365f 100644
--- a/adapters/gamoshi/usersync_test.go
+++ b/adapters/gamoshi/usersync_test.go
@@ -25,6 +25,5 @@ func TestGamoshiSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://rtb.gamoshi.io/user_sync_prebid?gdpr=&consent=&us_privacy=anyValue&rurl=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dgamoshi%26gdpr%3D%7B%7B.GDPR%7D%7D%26gdpr_consent%3D%7B%7B.GDPRConsent%7D%7D%26uid%3D%5Bgusr%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 644, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/grid/usersync_test.go b/adapters/grid/usersync_test.go
index 99730b5d..2d7f3fc6 100644
--- a/adapters/grid/usersync_test.go
+++ b/adapters/grid/usersync_test.go
@@ -25,6 +25,5 @@ func TestGridSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dgrid%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 686, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/gumgum/usersync_test.go b/adapters/gumgum/usersync_test.go
index 9c6dc420..9b7c7aa4 100644
--- a/adapters/gumgum/usersync_test.go
+++ b/adapters/gumgum/usersync_test.go
@@ -30,6 +30,5 @@ func TestGumGumSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://rtb.gumgum.com/usync/prbds2s?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&r=localhost%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 61, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/improvedigital/improvedigitaltest/exemplary/native.json b/adapters/improvedigital/improvedigitaltest/exemplary/native.json
new file mode 100644
index 00000000..3309b35a
--- /dev/null
+++ b/adapters/improvedigital/improvedigitaltest/exemplary/native.json
@@ -0,0 +1,161 @@
+{
+  "mockBidRequest": {
+    "id": "26f14780-8ef8-4f41-b70c-c4d062237df6",
+    "source": {
+      "tid": "26f14780-8ef8-4f41-b70c-c4d062237df6",
+      "ext": {
+        "schain": {
+          "ver": "1.0",
+          "complete": 1,
+          "nodes": [
+            { "asi": "example.com", "hp": 1, "sid": "1234abc" }
+          ]
+        }
+      }
+    },
+    "tmax": 1000,
+    "imp": [
+      {
+        "id": "native",
+        "ext": { "improvedigital": { "placementId": 1234 } },
+        "native": {
+          "request": "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1]}],\"assets\":[{\"required\":1,\"title\":{\"len\":80}},{\"required\":1,\"data\":{\"type\":2}},{\"required\":0,\"data\":{\"type\":12}},{\"required\":0,\"img\":{\"type\":3,\"wmin\":300,\"hmin\":225,\"ext\":{\"aspectratios\":[\"4:3\"]}}},{\"required\":0,\"img\":{\"type\":1,\"w\":128,\"h\":128}},{\"required\":0,\"data\":{\"type\":3}},{\"required\":0,\"data\":{\"type\":6}}]}",
+          "ver": "1.2"
+        }
+      }
+    ],
+    "ext": {
+      "prebid": {
+        "targeting": {
+          "includewinners": true,
+          "includebidderkeys": false
+        }
+      }
+    },
+    "site": {
+      "publisher": { "id": "pubid" },
+      "page": "example.com"
+    },
+    "device": { "w": 1581, "h": 922, "ip": "1.1.1.1" },
+    "regs": { "ext": { "gdpr": 0 } },
+    "user": {
+      "ext": {
+        "consent": "XYZ"
+      }
+    }
+  },
+  "httpcalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/pbs",
+        "body": {
+          "id": "26f14780-8ef8-4f41-b70c-c4d062237df6",
+          "imp": [
+            {
+              "id": "native",
+              "native": {
+                "request": "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1]}],\"assets\":[{\"required\":1,\"title\":{\"len\":80}},{\"required\":1,\"data\":{\"type\":2}},{\"required\":0,\"data\":{\"type\":12}},{\"required\":0,\"img\":{\"type\":3,\"wmin\":300,\"hmin\":225,\"ext\":{\"aspectratios\":[\"4:3\"]}}},{\"required\":0,\"img\":{\"type\":1,\"w\":128,\"h\":128}},{\"required\":0,\"data\":{\"type\":3}},{\"required\":0,\"data\":{\"type\":6}}]}",
+                "ver": "1.2"
+              },
+              "ext": { "improvedigital": { "placementId": 1234 } }
+            }
+          ],
+          "site": {
+            "page": "example.com",
+            "publisher": { "id": "pubid" }
+          },
+          "device": {
+            "ip": "1.1.1.1",
+            "h": 922,
+            "w": 1581
+          },
+          "user": {
+            "ext": {
+              "consent": "XYZ"
+            }
+          },
+          "tmax": 1000,
+          "source": {
+            "tid": "26f14780-8ef8-4f41-b70c-c4d062237df6",
+            "ext": {
+              "schain": {
+                "ver": "1.0",
+                "complete": 1,
+                "nodes": [
+                  {
+                    "asi": "example.com",
+                    "hp": 1,
+                    "sid": "1234abc"
+                  }
+                ]
+              }
+            }
+          },
+          "regs": { "ext": { "gdpr": 0 } },
+          "ext": {
+            "prebid": {
+              "targeting": {
+                "includewinners": true,
+                "includebidderkeys": false
+              }
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "26f14780-8ef8-4f41-b70c-c4d062237df6",
+          "cur": "USD",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "ext": {
+                    "improvedigital": {
+                      "brand_name": "AdvertiserABC",
+                      "bidder_id": 301
+                    }
+                  },
+                  "crid": "14065",
+                  "id": "d4f04449-ba04-4d7c-bb34-dc0fc5240f59",
+                  "price": 0.01,
+                  "adm": "{\"assets\":[{\"title\":{\"text\":\"Luxury Mars Cruises\"},\"id\":1},{\"id\":2,\"data\":{\"type\":2,\"value\":\"Visit the planet in a luxury spaceship.\"}},{\"id\":3,\"data\":{\"type\":12,\"value\":\"Book today\"}},{\"id\":4,\"img\":{\"h\":250,\"type\":3,\"url\":\"http://hb.improvedigital.com/creatives/display/300x250.jpg\",\"w\":300}},{\"id\":6,\"data\":{\"type\":3,\"value\":\"3.8\"}},{\"id\":7,\"data\":{\"type\":6,\"value\":\"FREE\"}}],\"link\":{\"clicktrackers\":[\"http://localhost.localdomain/click/\"],\"url\":\"http://www.iponweb.com/careers/\"}}",
+                  "adomain": ["example.com"],
+                  "impid": "native",
+                  "cid": "25076"
+                }
+              ],
+              "seat": "improvedigital"
+            }
+          ]
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "d4f04449-ba04-4d7c-bb34-dc0fc5240f59",
+            "impid": "native",
+            "price": 0.01,
+            "adm": "{\"assets\":[{\"title\":{\"text\":\"Luxury Mars Cruises\"},\"id\":1},{\"id\":2,\"data\":{\"type\":2,\"value\":\"Visit the planet in a luxury spaceship.\"}},{\"id\":3,\"data\":{\"type\":12,\"value\":\"Book today\"}},{\"id\":4,\"img\":{\"h\":250,\"type\":3,\"url\":\"http://hb.improvedigital.com/creatives/display/300x250.jpg\",\"w\":300}},{\"id\":6,\"data\":{\"type\":3,\"value\":\"3.8\"}},{\"id\":7,\"data\":{\"type\":6,\"value\":\"FREE\"}}],\"link\":{\"clicktrackers\":[\"http://localhost.localdomain/click/\"],\"url\":\"http://www.iponweb.com/careers/\"}}",
+            "adomain": ["example.com"],
+            "cid": "25076",
+            "crid": "14065",
+            "ext": {
+              "improvedigital": {
+                "brand_name": "AdvertiserABC",
+                "bidder_id": 301
+              }
+            }
+          },
+          "type": "native"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/improvedigital/improvedigitaltest/params/race/native.json b/adapters/improvedigital/improvedigitaltest/params/race/native.json
new file mode 100644
index 00000000..0de1d580
--- /dev/null
+++ b/adapters/improvedigital/improvedigitaltest/params/race/native.json
@@ -0,0 +1,12 @@
+{
+    "placementId": 123,
+    "publisherId": 321,
+    "placementKey": "uniq_name",
+    "size": {
+        "w": 100,
+        "h": 100
+    },
+    "keyValues": {
+        "testKey1": ["testValueA", "testValueB"]
+    }
+}
diff --git a/adapters/improvedigital/improvedigitaltest/supplemental/native.json b/adapters/improvedigital/improvedigitaltest/supplemental/native.json
deleted file mode 100644
index 3090700a..00000000
--- a/adapters/improvedigital/improvedigitaltest/supplemental/native.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
-    "mockBidRequest": {
-        "id": "test-request-id",
-        "imp": [{
-            "id": "test-imp-id",
-            "native": {
-                "ver": "1.1"
-            },
-            "ext": {
-                "bidder": {
-                    "placementId": 13245
-                }
-            }
-        }]
-    },
-    "httpCalls": [{
-        "expectedRequest": {
-            "uri": "http://localhost/pbs",
-            "body": {
-                "id": "test-request-id",
-                "imp": [{
-                    "id": "test-imp-id",
-					"native": {
-						"request": "",
-		                "ver": "1.1"
-		            },
-                    "ext": {
-                        "bidder": {
-                            "placementId": 13245
-                        }
-                    }
-                }]
-            }
-        },
-		"mockResponse": {
-            "status": 200,
-            "body": {
-                "id": "test-request-id",
-                "seatbid": [{
-                    "seat": "improvedigital",
-                    "bid": [{
-                        "id": "randomid",
-                        "impid": "test-imp-id",
-                        "price": 0.500000,
-                        "adid": "12345678",
-                        "adm": "some-test-native",
-                        "cid": "987",
-                        "crid": "12345678",
-                        "h": 250,
-                        "w": 300
-                    }]
-                }],
-                "cur": "USD"
-            }
-        }
-    }],
-
-    "expectedMakeBidsErrors": [
-        {
-            "value":  "Unknown impression type for ID: \"test-imp-id\"",
-            "comparison": "literal"
-        }
-    ]
-}
diff --git a/adapters/improvedigital/usersync_test.go b/adapters/improvedigital/usersync_test.go
index 35ea89cf..9892e0cc 100644
--- a/adapters/improvedigital/usersync_test.go
+++ b/adapters/improvedigital/usersync_test.go
@@ -30,6 +30,5 @@ func TestImprovedigitalSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ad.360yield.com/server_match?gdpr=A&gdpr_consent=B&us_privacy=C&r=%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%7BPUB_USER_ID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 253, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/invibes/usersync_test.go b/adapters/invibes/usersync_test.go
index 3f715f6b..49288622 100644
--- a/adapters/invibes/usersync_test.go
+++ b/adapters/invibes/usersync_test.go
@@ -26,7 +26,6 @@ func TestInvibesSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "http://localhost:56479/home/getLid?gdpr=1&gdpr_consent=abc&us_privacy=&redirectUri=test.com%2Fsetuid%3Fbidder%3Dinvibes%26gdpr%3D1%26gdpr_consent%3Dabc%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 436, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 
 }
diff --git a/adapters/ix/usersync_test.go b/adapters/ix/usersync_test.go
index 10f91da1..3288b1ae 100644
--- a/adapters/ix/usersync_test.go
+++ b/adapters/ix/usersync_test.go
@@ -20,6 +20,5 @@ func TestIxSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ssum-sec.casalemedia.com/usermatchredir?s=184932&cb=localhost%2Fsetuid%3Fbidder%3Dix%26gdpr%3D%26gdpr_consent%3D%26uid%3D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 10, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/jixie/jixie_test.go b/adapters/jixie/jixie_test.go
index 968fb4fd..289dd241 100644
--- a/adapters/jixie/jixie_test.go
+++ b/adapters/jixie/jixie_test.go
@@ -1,10 +1,11 @@
 package jixie
 
 import (
+	"testing"
+
 	"github.com/prebid/prebid-server/adapters/adapterstest"
 	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/openrtb_ext"
-	"testing"
 )
 
 func TestJsonSamples(t *testing.T) {
diff --git a/adapters/jixie/usersync_test.go b/adapters/jixie/usersync_test.go
index 5be5e514..57548243 100644
--- a/adapters/jixie/usersync_test.go
+++ b/adapters/jixie/usersync_test.go
@@ -1,10 +1,10 @@
 package jixie
 
 import (
-	"github.com/prebid/prebid-server/privacy"
 	"testing"
 	"text/template"
 
+	"github.com/prebid/prebid-server/privacy"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -20,6 +20,5 @@ func TestJixieSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://id.jixie.io/api/sync?pid=&gdpr=&gdpr_consent=&us_privacy=&redirect=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Djixie%26gdpr%3D%26gdpr_consent%3D%26uid%3D%25%25JXUID%25%25", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/krushmedia/usersync_test.go b/adapters/krushmedia/usersync_test.go
index b58f2f1b..765b0faa 100644
--- a/adapters/krushmedia/usersync_test.go
+++ b/adapters/krushmedia/usersync_test.go
@@ -29,6 +29,5 @@ func TestKrushmediaSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://cs.krushmedia.com/4e4abdd5ecc661643458a730b1aa927d.gif?gdpr=0&gdpr_consent=allGdpr&us_privacy=1-YY&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dkrushmedia%26uid%3D%5BUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/lifestreet/usersync_test.go b/adapters/lifestreet/usersync_test.go
index 8fee0935..e41217fe 100644
--- a/adapters/lifestreet/usersync_test.go
+++ b/adapters/lifestreet/usersync_test.go
@@ -25,6 +25,5 @@ func TestLifestreetSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ads.lfstmedia.com/idsync/137062?synced=1&ttl=1s&rurl=localhost%2Fsetuid%3Fbidder%3Dlifestreet%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24%24visitor_cookie%24%24", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 67, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/lockerdome/usersync_test.go b/adapters/lockerdome/usersync_test.go
index b5dea226..3a2bd7f3 100644
--- a/adapters/lockerdome/usersync_test.go
+++ b/adapters/lockerdome/usersync_test.go
@@ -20,6 +20,5 @@ func TestLockerDomeSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://lockerdome.com/usync/prebidserver?pid=&gdpr=&gdpr_consent=&us_privacy=&redirect=https%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dlockerdome%26gdpr%3D%26gdpr_consent%3D%26uid%3D%7B%7Buid%7D%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/logicad/usersync_test.go b/adapters/logicad/usersync_test.go
index 89d6207d..e8b10c66 100644
--- a/adapters/logicad/usersync_test.go
+++ b/adapters/logicad/usersync_test.go
@@ -26,6 +26,5 @@ func TestLogicadSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://localhost/cookiesender?r=true&gdpr=1&gdpr_consent=A&ru=localhost%2Fsetuid%3Fbidder%3Dlogicad%26gdpr%3D1%26gdpr_consent%3DA%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/lunamedia/usersync_test.go b/adapters/lunamedia/usersync_test.go
index c9fe2032..24cd740d 100644
--- a/adapters/lunamedia/usersync_test.go
+++ b/adapters/lunamedia/usersync_test.go
@@ -26,6 +26,5 @@ func TestLunaMediaSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://api.lunamedia.io/xp/user-sync?acctid={aid}&&redirect=localhost/setuid?bidder=lunamedia&gdpr=1&gdpr_consent=A&uid=$UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/marsmedia/usersync_test.go b/adapters/marsmedia/usersync_test.go
index f019c014..975af65f 100644
--- a/adapters/marsmedia/usersync_test.go
+++ b/adapters/marsmedia/usersync_test.go
@@ -30,7 +30,6 @@ func TestMarsmediaSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr=A&gdpr_consent=B&us_privacy=C&redirect=localhost:8000%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%24%7BUUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 
 }
diff --git a/adapters/mediafuse/usersync_test.go b/adapters/mediafuse/usersync_test.go
index 30b5b535..e3dfa068 100644
--- a/adapters/mediafuse/usersync_test.go
+++ b/adapters/mediafuse/usersync_test.go
@@ -25,6 +25,5 @@ func TestMediafuseSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//sync.hbmp.mediafuse.com/csync?t=p&ep=0&redir=localhost%2Fsetuid%3Fbidder%3Dmediafuse%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%7Buid%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 411, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/mgid/usersync_test.go b/adapters/mgid/usersync_test.go
index 2ce634ee..3fa5a151 100644
--- a/adapters/mgid/usersync_test.go
+++ b/adapters/mgid/usersync_test.go
@@ -25,6 +25,5 @@ func TestMgidSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://cm.mgid.com/m?cdsp=363893&adu=https%3A//external.com%2Fsetuid%3Fbidder%3Dmgid%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%7Bmuidn%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 358, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/nanointeractive/usersync_test.go b/adapters/nanointeractive/usersync_test.go
index fa786649..4d816ab7 100644
--- a/adapters/nanointeractive/usersync_test.go
+++ b/adapters/nanointeractive/usersync_test.go
@@ -31,6 +31,5 @@ func TestNewNanoInteractiveSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ad.audiencemanager.de/hbs/cookie_sync?gdpr=1&consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw&us_privacy=1NYN&redirectUri=http%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dnanointeractive%26gdpr%3D1%26gdpr_consent%3DBONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 72, userSync.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/ninthdecimal/usersync_test.go b/adapters/ninthdecimal/usersync_test.go
index ee121434..e722a2b6 100755
--- a/adapters/ninthdecimal/usersync_test.go
+++ b/adapters/ninthdecimal/usersync_test.go
@@ -26,6 +26,5 @@ func TestNinthDecimalSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://rtb.ninthdecimal.com/xp/user-sync?acctid={aid}&&redirect=localhost/setuid?bidder=ninthdecimal&gdpr=1&gdpr_consent=A&uid=$UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/onetag/usersync_test.go b/adapters/onetag/usersync_test.go
index 31892e6d..21f4837d 100644
--- a/adapters/onetag/usersync_test.go
+++ b/adapters/onetag/usersync_test.go
@@ -20,5 +20,4 @@ func TestOneTagSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://onetag-sys.com/usync/?redir=", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 241, syncer.GDPRVendorID())
 }
diff --git a/adapters/openx/usersync_test.go b/adapters/openx/usersync_test.go
index cdbb7da8..14ec38be 100644
--- a/adapters/openx/usersync_test.go
+++ b/adapters/openx/usersync_test.go
@@ -20,6 +20,5 @@ func TestOpenxSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://rtb.openx.net/sync/prebid?gdpr=&gdpr_consent=&r=localhost%2Fsetuid%3Fbidder%3Dopenx%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 69, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/pubmatic/usersync_test.go b/adapters/pubmatic/usersync_test.go
index d6cd9f78..0f4d2e85 100644
--- a/adapters/pubmatic/usersync_test.go
+++ b/adapters/pubmatic/usersync_test.go
@@ -30,6 +30,5 @@ func TestPubmaticSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ads.pubmatic.com/AdServer/js/user_sync.html?gdpr=A&gdpr_consent=B&us_privacy=C&predirect=localhost%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 76, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/pulsepoint/usersync_test.go b/adapters/pulsepoint/usersync_test.go
index e1680fd2..7cfea57c 100644
--- a/adapters/pulsepoint/usersync_test.go
+++ b/adapters/pulsepoint/usersync_test.go
@@ -20,6 +20,5 @@ func TestPulsepointSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//bh.contextweb.com/rtset?pid=561205&ev=1&rurl=http%3A%2F%2Flocalhost%2Fsetuid%3Fbidder%3Dpulsepoint%26gdpr%3D%26gdpr_consent%3D%26uid%3D%25%25VGUID%25%25", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 81, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/rhythmone/usersync_test.go b/adapters/rhythmone/usersync_test.go
index 85ecba2a..97920fb4 100644
--- a/adapters/rhythmone/usersync_test.go
+++ b/adapters/rhythmone/usersync_test.go
@@ -30,6 +30,5 @@ func TestRhythmoneSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://sync.1rx.io/usersync2/rmphb?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redir=localhost%2Fsetuid%3Fbidder%3Drhythmone%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D%5BRX_UUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 36, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/rtbhouse/usersync_test.go b/adapters/rtbhouse/usersync_test.go
index bb139f7a..a7cb2590 100644
--- a/adapters/rtbhouse/usersync_test.go
+++ b/adapters/rtbhouse/usersync_test.go
@@ -25,6 +25,5 @@ func TestRTBHouseSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://creativecdn.com/cm-notify?pi=prebidsrvtst&gdpr=0&gdpr_consent=", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, rtbHouseGDPRVendorID, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/rubicon/usersync_test.go b/adapters/rubicon/usersync_test.go
index 646ebff2..eca40562 100644
--- a/adapters/rubicon/usersync_test.go
+++ b/adapters/rubicon/usersync_test.go
@@ -25,7 +25,6 @@ func TestRubiconSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://pixel.rubiconproject.com/exchange/sync.php?p=prebid&gdpr=0&gdpr_consent=", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 52, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 	assert.Equal(t, "rubicon", syncer.FamilyName())
 }
diff --git a/adapters/sharethrough/usersync_test.go b/adapters/sharethrough/usersync_test.go
index 48023295..00b3c427 100644
--- a/adapters/sharethrough/usersync_test.go
+++ b/adapters/sharethrough/usersync_test.go
@@ -25,7 +25,6 @@ func TestSharethroughSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://match.sharethrough.com?gdpr=0&gdpr_consent=", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 80, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 	assert.Equal(t, "sharethrough", syncer.FamilyName())
 }
diff --git a/adapters/smartadserver/usersync_test.go b/adapters/smartadserver/usersync_test.go
index c4e66606..319ce5b5 100644
--- a/adapters/smartadserver/usersync_test.go
+++ b/adapters/smartadserver/usersync_test.go
@@ -30,6 +30,5 @@ func TestSmartadserverSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ssbsync.smartadserver.com/getuid?gdpr=1&gdpr_consent=COyASAoOyASAoAfAAAENAfCAAAAAAAAAAAAAAAAAAAAA&us_privacy=1YNN&url=localhost%2Fsetuid%3Fbidder%3Dsmartadserver%26gdpr%3D1%26gdpr_consent%3DCOyASAoOyASAoAfAAAENAfCAAAAAAAAAAAAAAAAAAAAA%26uid%3D%5Bsas_uid%5D%22", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 45, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/smartrtb/usersync_test.go b/adapters/smartrtb/usersync_test.go
index ae3ae5dc..68a8452a 100644
--- a/adapters/smartrtb/usersync_test.go
+++ b/adapters/smartrtb/usersync_test.go
@@ -15,6 +15,5 @@ func TestSmartRTBSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "http://market-east.smrtb.com/sync/all?nid=smartrtb&gdpr=&gdpr_consent=&url=localhost%2Fsetuid%3Fbidder%smartrtb%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/smartyads/usersync_test.go b/adapters/smartyads/usersync_test.go
index ed7fc07b..4f94591c 100644
--- a/adapters/smartyads/usersync_test.go
+++ b/adapters/smartyads/usersync_test.go
@@ -29,6 +29,5 @@ func TestSmartyAdsSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://as.ck-ie.com/prebid.gif?gdpr=0&gdpr_consent=ANDFJDS&us_privacy=1-YY&redir=http%3A%2F%2Flocalhost%3A8000%2Fsetuid%3Fbidder%3Dsmartyads%26uid%3D%5BUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/somoaudience/usersync_test.go b/adapters/somoaudience/usersync_test.go
index 86460506..2367a567 100644
--- a/adapters/somoaudience/usersync_test.go
+++ b/adapters/somoaudience/usersync_test.go
@@ -20,6 +20,5 @@ func TestSomoaudienceSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//publisher-east.mobileadtrading.com/usersync?ru=localhost%2Fsetuid%3Fbidder%3Dsomoaudience%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24%7BUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 341, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/sonobi/usersync_test.go b/adapters/sonobi/usersync_test.go
index bfe5859e..995c3757 100644
--- a/adapters/sonobi/usersync_test.go
+++ b/adapters/sonobi/usersync_test.go
@@ -25,6 +25,5 @@ func TestSonobiSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//sync.go.sonobi.com/us.gif?loc=external.com%2Fsetuid%3Fbidder%3Dsonobi%26consent_string%3D0%26gdpr%3D%26uid%3D%5BUID%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 104, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/sovrn/usersync_test.go b/adapters/sovrn/usersync_test.go
index 4a4dfd9d..6c35ecdb 100644
--- a/adapters/sovrn/usersync_test.go
+++ b/adapters/sovrn/usersync_test.go
@@ -25,6 +25,5 @@ func TestSovrnSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ap.lijit.com/pixel?redir=external.com%2Fsetuid%3Fbidder%3Dsovrn%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 13, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/synacormedia/usersync_test.go b/adapters/synacormedia/usersync_test.go
index 538efb30..ce45353c 100644
--- a/adapters/synacormedia/usersync_test.go
+++ b/adapters/synacormedia/usersync_test.go
@@ -20,6 +20,5 @@ func TestSynacormediaSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//sync.technoratimedia.com/services?srv=cs&pid=70&cb=localhost%2Fsetuid%3Fbidder%3Dsynacormedia%26uid%3D%5BUSER_ID%5D", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/tappx/usersync_test.go b/adapters/tappx/usersync_test.go
index 65919b9f..992a35de 100644
--- a/adapters/tappx/usersync_test.go
+++ b/adapters/tappx/usersync_test.go
@@ -30,6 +30,5 @@ func TestTappxSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//testing.ssp.tappx.com/cs/usersync.php?gdpr_optin=1&gdpr_consent=A&us_privacy=1YNN&type=iframe&ruid=localhost%2Fsetuid%3Fbidder%3Dtappx%26gdpr%3D1%26gdpr_consent%3DA%26uid%3D%7B%7BTPPXUID%7D%7D", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 628, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/telaria/usersync_test.go b/adapters/telaria/usersync_test.go
index 4896b253..f019ed5c 100644
--- a/adapters/telaria/usersync_test.go
+++ b/adapters/telaria/usersync_test.go
@@ -26,7 +26,6 @@ func TestTelariaSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://pbs.publishers.tremorhub.com/pubsync?gdpr=0&gdpr_consent=", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 202, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 	assert.Equal(t, "telaria", syncer.FamilyName())
 
diff --git a/adapters/triplelift/usersync_test.go b/adapters/triplelift/usersync_test.go
index 1731b22d..012e33a4 100644
--- a/adapters/triplelift/usersync_test.go
+++ b/adapters/triplelift/usersync_test.go
@@ -20,6 +20,5 @@ func TestTripleliftSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//eb2.3lift.com/getuid?gdpr=&cmp_cs=&us_privacy=&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 28, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/triplelift_native/usersync_test.go b/adapters/triplelift_native/usersync_test.go
index df0757ed..7fd878b7 100644
--- a/adapters/triplelift_native/usersync_test.go
+++ b/adapters/triplelift_native/usersync_test.go
@@ -20,6 +20,5 @@ func TestTripleliftSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//eb2.3lift.com/getuid?gdpr=&cmp_cs=&us_privacy=&redir=https%3A%2F%2Feb2.3lift.com%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 28, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/trustx/usersync_test.go b/adapters/trustx/usersync_test.go
index ced0d215..ba371bc2 100644
--- a/adapters/trustx/usersync_test.go
+++ b/adapters/trustx/usersync_test.go
@@ -25,6 +25,5 @@ func TestTrustXSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dgrid%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 686, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/ucfunnel/usersync_test.go b/adapters/ucfunnel/usersync_test.go
index 45320b8c..204de978 100644
--- a/adapters/ucfunnel/usersync_test.go
+++ b/adapters/ucfunnel/usersync_test.go
@@ -25,6 +25,5 @@ func TestUcfunnelSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//sync.aralego.com/idsync?gdpr=0&redirect=externalURL.com%2Fsetuid%3Fbidder%3Ducfunnel%26uid%3DSspCookieUserId", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 607, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/unruly/usersync_test.go b/adapters/unruly/usersync_test.go
index 2f0e07d8..f0702ceb 100644
--- a/adapters/unruly/usersync_test.go
+++ b/adapters/unruly/usersync_test.go
@@ -30,6 +30,5 @@ func TestUnrulySyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://usermatch.targeting.unrulymedia.com/pbsync?gdpr=A&consent=B&us_privacy=C&rurl=%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "iframe", syncInfo.Type)
-	assert.EqualValues(t, 162, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/valueimpression/usersync_test.go b/adapters/valueimpression/usersync_test.go
index ffb3f372..7b3a13c5 100644
--- a/adapters/valueimpression/usersync_test.go
+++ b/adapters/valueimpression/usersync_test.go
@@ -30,6 +30,5 @@ func TestValueImpressionSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://rtb.valueimpression.com/usersync?gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&redirectUri=http%3A%2F%2Flocalhost:8000%2Fsetuid%3Fbidder%3Dvalueimpression%26gdpr%3D1%26gdpr_consent%3DBOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/verizonmedia/usersync_test.go b/adapters/verizonmedia/usersync_test.go
index ad77ef0e..9dd1ae70 100644
--- a/adapters/verizonmedia/usersync_test.go
+++ b/adapters/verizonmedia/usersync_test.go
@@ -19,5 +19,4 @@ func TestVerizonMediaSyncer(t *testing.T) {
 
 	assert.NoError(t, err)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 25, syncer.GDPRVendorID())
 }
diff --git a/adapters/visx/usersync_test.go b/adapters/visx/usersync_test.go
index b410cda6..ec4cf82b 100644
--- a/adapters/visx/usersync_test.go
+++ b/adapters/visx/usersync_test.go
@@ -30,6 +30,5 @@ func TestVisxSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://t.visx.net/s2s_sync?gdpr=A&gdpr_consent=B&us_privacy=C&redir=%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%24%7BUUID%7D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 154, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/adapters/vrtcal/usersync_test.go b/adapters/vrtcal/usersync_test.go
index 26e5838d..7f8ca220 100644
--- a/adapters/vrtcal/usersync_test.go
+++ b/adapters/vrtcal/usersync_test.go
@@ -25,7 +25,6 @@ func TestVrtcalSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "http://usync-prebid.vrtcal.com/s?gdpr=0&gdpr_consent=", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 	assert.Equal(t, "vrtcal", syncer.FamilyName())
 }
diff --git a/adapters/yieldlab/usersync_test.go b/adapters/yieldlab/usersync_test.go
index 3892c16b..eabd46f6 100644
--- a/adapters/yieldlab/usersync_test.go
+++ b/adapters/yieldlab/usersync_test.go
@@ -21,6 +21,5 @@ func TestYieldlabSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "https://ad.yieldlab.net/mr?t=2&pid=9140838&gdpr=0&gdpr_consent=&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldlab%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%25%25YL_UID%25%25", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 70, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/yieldmo/usersync_test.go b/adapters/yieldmo/usersync_test.go
index 598710ec..5d12c63e 100644
--- a/adapters/yieldmo/usersync_test.go
+++ b/adapters/yieldmo/usersync_test.go
@@ -25,6 +25,5 @@ func TestYieldmoSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//ads.yieldmo.com/pbsync?gdpr=0&gdpr_consent=&us_privacy=&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 173, syncer.GDPRVendorID())
 	assert.False(t, syncInfo.SupportCORS)
 }
diff --git a/adapters/yieldone/usersync_test.go b/adapters/yieldone/usersync_test.go
index 902f3b66..c4d0fee9 100644
--- a/adapters/yieldone/usersync_test.go
+++ b/adapters/yieldone/usersync_test.go
@@ -25,6 +25,5 @@ func TestYieldoneSyncer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dyieldone%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%24UID", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
-	assert.EqualValues(t, 0, syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
 }
diff --git a/config/bidderinfo_test.go b/config/bidderinfo_test.go
index 2d9d53ec..62a0b853 100644
--- a/config/bidderinfo_test.go
+++ b/config/bidderinfo_test.go
@@ -13,6 +13,7 @@ const testInfoFilesPath = "./test/bidder-info"
 const testYAML = `
 maintainer:
   email: "some-email@domain.com"
+gvlVendorID: 42
 capabilities:
   app:
     mediaTypes:
@@ -36,12 +37,13 @@ func TestLoadBidderInfoFromDisk(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	expected := map[string]BidderInfo{
+	expected := BidderInfos{
 		bidder: {
 			Enabled: true,
 			Maintainer: &MaintainerInfo{
 				Email: "some-email@domain.com",
 			},
+			GVLVendorID: 42,
 			Capabilities: &CapabilitiesInfo{
 				App: &PlatformInfo{
 					MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeNative},
@@ -63,7 +65,7 @@ func TestLoadBidderInfo(t *testing.T) {
 		givenConfigs  map[string]Adapter
 		givenContent  string
 		givenError    error
-		expectedInfo  map[string]BidderInfo
+		expectedInfo  BidderInfos
 		expectedError string
 	}{
 		{
@@ -76,6 +78,7 @@ func TestLoadBidderInfo(t *testing.T) {
 					Maintainer: &MaintainerInfo{
 						Email: "some-email@domain.com",
 					},
+					GVLVendorID: 42,
 					Capabilities: &CapabilitiesInfo{
 						App: &PlatformInfo{
 							MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeNative},
@@ -97,6 +100,7 @@ func TestLoadBidderInfo(t *testing.T) {
 					Maintainer: &MaintainerInfo{
 						Email: "some-email@domain.com",
 					},
+					GVLVendorID: 42,
 					Capabilities: &CapabilitiesInfo{
 						App: &PlatformInfo{
 							MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeNative},
@@ -118,6 +122,7 @@ func TestLoadBidderInfo(t *testing.T) {
 					Maintainer: &MaintainerInfo{
 						Email: "some-email@domain.com",
 					},
+					GVLVendorID: 42,
 					Capabilities: &CapabilitiesInfo{
 						App: &PlatformInfo{
 							MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeNative},
@@ -139,6 +144,7 @@ func TestLoadBidderInfo(t *testing.T) {
 					Maintainer: &MaintainerInfo{
 						Email: "some-email@domain.com",
 					},
+					GVLVendorID: 42,
 					Capabilities: &CapabilitiesInfo{
 						App: &PlatformInfo{
 							MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeNative},
@@ -186,3 +192,19 @@ type fakeInfoReader struct {
 func (r fakeInfoReader) Read(bidder string) ([]byte, error) {
 	return []byte(r.content), r.err
 }
+
+func TestToGVLVendorIDMap(t *testing.T) {
+	givenBidderInfos := BidderInfos{
+		"bidderA": BidderInfo{Enabled: true, GVLVendorID: 0},
+		"bidderB": BidderInfo{Enabled: true, GVLVendorID: 100},
+		"bidderC": BidderInfo{Enabled: false, GVLVendorID: 0},
+		"bidderD": BidderInfo{Enabled: false, GVLVendorID: 200},
+	}
+
+	expectedGVLVendorIDMap := map[openrtb_ext.BidderName]uint16{
+		"bidderB": 100,
+	}
+
+	result := givenBidderInfos.ToGVLVendorIDMap()
+	assert.Equal(t, expectedGVLVendorIDMap, result)
+}
diff --git a/config/test/bidder-info/someBidder.yaml b/config/test/bidder-info/someBidder.yaml
index b5216f0f..232b73d0 100644
--- a/config/test/bidder-info/someBidder.yaml
+++ b/config/test/bidder-info/someBidder.yaml
@@ -1,5 +1,6 @@
 maintainer:
   email: "some-email@domain.com"
+gvlVendorID: 42
 capabilities:
   app:
     mediaTypes:
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index 768e6059..892b0579 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -48,7 +48,7 @@ type testConfigValues struct {
 	AliasJSON           string   `json:"aliases"`
 	BlacklistedAccounts []string `json:"blacklistedAccts"`
 	BlacklistedApps     []string `json:"blacklistedApps"`
-	AdapterList         []string `json:"disabledAdapters"`
+	DisabledAdapters    []string `json:"disabledAdapters"`
 }
 
 func TestJsonSampleRequests(t *testing.T) {
@@ -229,9 +229,9 @@ func (tc *testConfigValues) getBlackListedAccountMap() map[string]bool {
 func (tc *testConfigValues) getAdaptersConfigMap() map[string]config.Adapter {
 	var adaptersConfig map[string]config.Adapter
 
-	if len(tc.AdapterList) > 0 {
-		adaptersConfig = make(map[string]config.Adapter, len(tc.AdapterList))
-		for _, adapterName := range tc.AdapterList {
+	if len(tc.DisabledAdapters) > 0 {
+		adaptersConfig = make(map[string]config.Adapter, len(tc.DisabledAdapters))
+		for _, adapterName := range tc.DisabledAdapters {
 			adaptersConfig[adapterName] = config.Adapter{Disabled: true}
 		}
 	}
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index fc98608e..87c98f23 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -462,8 +462,3 @@ func (s fakeSyncer) FamilyName() string {
 func (s fakeSyncer) GetUsersyncInfo(privacyPolicies privacy.Policies) (*usersync.UsersyncInfo, error) {
 	return nil, nil
 }
-
-// GDPRVendorID implements the Usersyncer interface with a no-op.
-func (s fakeSyncer) GDPRVendorID() uint16 {
-	return 0
-}
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index b829ddd7..dbf8a022 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -135,10 +135,6 @@ func TestSingleBidder(t *testing.T) {
 		if len(seatBid.httpCalls) != test.httpCallsLen {
 			t.Errorf("The bidder shouldn't log HttpCalls when request.test == 0. Found %d", len(seatBid.httpCalls))
 		}
-
-		if len(seatBid.ext) != 0 {
-			t.Errorf("The bidder shouldn't define any seatBid.ext. Got %s", string(seatBid.ext))
-		}
 	}
 }
 
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 7507ecef..f615d412 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -1823,7 +1823,7 @@ func TestCategoryMapping(t *testing.T) {
 		&bid1_4,
 	}
 
-	seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+	seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 	bidderName1 := openrtb_ext.BidderName("appnexus")
 
 	adapterBids[bidderName1] = &seatBid
@@ -1878,7 +1878,7 @@ func TestCategoryMappingNoIncludeBrandCategory(t *testing.T) {
 		&bid1_4,
 	}
 
-	seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+	seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 	bidderName1 := openrtb_ext.BidderName("appnexus")
 
 	adapterBids[bidderName1] = &seatBid
@@ -1930,7 +1930,7 @@ func TestCategoryMappingTranslateCategoriesNil(t *testing.T) {
 		&bid1_3,
 	}
 
-	seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+	seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 	bidderName1 := openrtb_ext.BidderName("appnexus")
 
 	adapterBids[bidderName1] = &seatBid
@@ -2012,7 +2012,7 @@ func TestCategoryMappingTranslateCategoriesFalse(t *testing.T) {
 		&bid1_3,
 	}
 
-	seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+	seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 	bidderName1 := openrtb_ext.BidderName("appnexus")
 
 	adapterBids[bidderName1] = &seatBid
@@ -2082,7 +2082,7 @@ func TestCategoryDedupe(t *testing.T) {
 			&bid1_5,
 		}
 
-		seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+		seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 		bidderName1 := openrtb_ext.BidderName("appnexus")
 
 		adapterBids[bidderName1] = &seatBid
@@ -2162,7 +2162,7 @@ func TestNoCategoryDedupe(t *testing.T) {
 			&bid1_5,
 		}
 
-		seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+		seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 		bidderName1 := openrtb_ext.BidderName("appnexus")
 
 		adapterBids[bidderName1] = &seatBid
@@ -2223,10 +2223,10 @@ func TestCategoryMappingBidderName(t *testing.T) {
 		&bid1_2,
 	}
 
-	seatBid1 := pbsOrtbSeatBid{innerBids1, "USD", nil, nil}
+	seatBid1 := pbsOrtbSeatBid{bids: innerBids1, currency: "USD"}
 	bidderName1 := openrtb_ext.BidderName("bidder1")
 
-	seatBid2 := pbsOrtbSeatBid{innerBids2, "USD", nil, nil}
+	seatBid2 := pbsOrtbSeatBid{bids: innerBids2, currency: "USD"}
 	bidderName2 := openrtb_ext.BidderName("bidder2")
 
 	adapterBids[bidderName1] = &seatBid1
@@ -2277,10 +2277,10 @@ func TestCategoryMappingBidderNameNoCategories(t *testing.T) {
 		&bid1_2,
 	}
 
-	seatBid1 := pbsOrtbSeatBid{innerBids1, "USD", nil, nil}
+	seatBid1 := pbsOrtbSeatBid{bids: innerBids1, currency: "USD"}
 	bidderName1 := openrtb_ext.BidderName("bidder1")
 
-	seatBid2 := pbsOrtbSeatBid{innerBids2, "USD", nil, nil}
+	seatBid2 := pbsOrtbSeatBid{bids: innerBids2, currency: "USD"}
 	bidderName2 := openrtb_ext.BidderName("bidder2")
 
 	adapterBids[bidderName1] = &seatBid1
@@ -2384,7 +2384,7 @@ func TestBidRejectionErrors(t *testing.T) {
 			innerBids = append(innerBids, &currentBid)
 		}
 
-		seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
+		seatBid := pbsOrtbSeatBid{bids: innerBids, currency: "USD"}
 
 		adapterBids[bidderName] = &seatBid
 
@@ -2442,10 +2442,10 @@ func TestCategoryMappingTwoBiddersOneBidEachNoCategorySamePrice(t *testing.T) {
 	for i := 1; i < 10; i++ {
 		adapterBids := make(map[openrtb_ext.BidderName]*pbsOrtbSeatBid)
 
-		seatBidApn1 := pbsOrtbSeatBid{innerBidsApn1, "USD", nil, nil}
+		seatBidApn1 := pbsOrtbSeatBid{bids: innerBidsApn1, currency: "USD"}
 		bidderNameApn1 := openrtb_ext.BidderName("appnexus1")
 
-		seatBidApn2 := pbsOrtbSeatBid{innerBidsApn2, "USD", nil, nil}
+		seatBidApn2 := pbsOrtbSeatBid{bids: innerBidsApn2, currency: "USD"}
 		bidderNameApn2 := openrtb_ext.BidderName("appnexus2")
 
 		adapterBids[bidderNameApn1] = &seatBidApn1
diff --git a/exchange/exchangetest/bid-ext-prebid-collision.json b/exchange/exchangetest/bid-ext-prebid-collision.json
new file mode 100644
index 00000000..054671ce
--- /dev/null
+++ b/exchange/exchangetest/bid-ext-prebid-collision.json
@@ -0,0 +1,90 @@
+{
+    "description": "Verifies bid.ext values are left alone from the adapter, except for overwriting bid.ext.prebid if the adapter ext includes a collision.",
+
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }]
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }]
+                },
+                "bidAdjustment": 1.0
+            },
+            "mockResponse": {
+                "pbsSeatBid": {
+                    "pbsBids": [{
+                        "ortbBid": {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "someField": "someValue",
+                                "prebid": {
+                                    "willBeOverwritten": "by core logic"
+                                }
+                            }
+                        },
+                        "bidType": "video"
+                    }]
+                }
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "some-request-id",
+            "seatbid": [{
+                "seat": "appnexus",
+                "bid": [{
+                    "id": "apn-bid",
+                    "impid": "my-imp-id",
+                    "price": 0.3,
+                    "w": 200,
+                    "h": 250,
+                    "crid": "creative-1",
+                    "ext": {
+                        "someField": "someValue",
+                        "prebid": {
+                            "type": "video"
+                        }
+                    }
+                }]
+            }]
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/bid-ext.json b/exchange/exchangetest/bid-ext.json
new file mode 100644
index 00000000..8211ac88
--- /dev/null
+++ b/exchange/exchangetest/bid-ext.json
@@ -0,0 +1,87 @@
+{
+    "description": "Verifies bid.ext values are left alone from the adapter, except for adding in bid.ext.prebid.",
+
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }]
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }]
+                },
+                "bidAdjustment": 1.0
+            },
+            "mockResponse": {
+                "pbsSeatBid": {
+                    "pbsBids": [{
+                        "ortbBid": {
+                            "id": "apn-bid",
+                            "impid": "my-imp-id",
+                            "price": 0.3,
+                            "w": 200,
+                            "h": 250,
+                            "crid": "creative-1",
+                            "ext": {
+                                "someField": "someValue"
+                            }
+                        },
+                        "bidType": "video"
+                    }]
+                }
+            }
+        }
+    },
+    "response": {
+        "bids": {
+            "id": "some-request-id",
+            "seatbid": [{
+                "seat": "appnexus",
+                "bid": [{
+                    "id": "apn-bid",
+                    "impid": "my-imp-id",
+                    "price": 0.3,
+                    "w": 200,
+                    "h": 250,
+                    "crid": "creative-1",
+                    "ext": {
+                        "someField": "someValue",
+                        "prebid": {
+                            "type": "video"
+                        }
+                    }
+                }]
+            }]
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/firstpartydata-imp-ext-multiple-prebid-bidders.json b/exchange/exchangetest/firstpartydata-imp-ext-multiple-prebid-bidders.json 
similarity index 98%
rename from exchange/exchangetest/firstpartydata-imp-ext-multiple-prebid-bidders.json
rename to exchange/exchangetest/firstpartydata-imp-ext-multiple-prebid-bidders.json 
index d62afccf..37654c45 100644
--- a/exchange/exchangetest/firstpartydata-imp-ext-multiple-prebid-bidders.json
+++ b/exchange/exchangetest/firstpartydata-imp-ext-multiple-prebid-bidders.json 
@@ -61,7 +61,6 @@
                             "bidder": {
                                 "placementId": 1
                             },
-                            "prebid": {},
                             "context": {
                                 "data": {
                                     "keywords": "prebid server example"
@@ -112,7 +111,6 @@
                                 "siteId": 2,
                                 "zoneId": 3
                             },
-                            "prebid": {},
                             "context": {
                                 "data": {
                                     "keywords": "prebid server example"
diff --git a/exchange/exchangetest/firstpartydata-imp-ext-one-prebid-bidder.json b/exchange/exchangetest/firstpartydata-imp-ext-one-prebid-bidder.json
index 1610b9ea..c931b0b9 100644
--- a/exchange/exchangetest/firstpartydata-imp-ext-one-prebid-bidder.json
+++ b/exchange/exchangetest/firstpartydata-imp-ext-one-prebid-bidder.json
@@ -56,7 +56,6 @@
                             "bidder": {
                                 "placementId": 1
                             },
-                            "prebid": {},
                             "context": {
                                 "data": {
                                     "keywords": "prebid server example"
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 0407b3c5..f089d705 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -55,6 +55,370 @@ func assertReq(t *testing.T, bidderRequests []BidderRequest,
 	}
 }
 
+func TestSplitImps(t *testing.T) {
+	testCases := []struct {
+		description   string
+		givenImps     []openrtb.Imp
+		expectedImps  map[string][]openrtb.Imp
+		expectedError string
+	}{
+		{
+			description:   "Nil",
+			givenImps:     nil,
+			expectedImps:  map[string][]openrtb.Imp{},
+			expectedError: "",
+		},
+		{
+			description:   "Empty",
+			givenImps:     []openrtb.Imp{},
+			expectedImps:  map[string][]openrtb.Imp{},
+			expectedError: "",
+		},
+		{
+			description: "1 Imp, 1 Bidder",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp1ParamA":"imp1ValueA"}}}}`)},
+			},
+			expectedImps: map[string][]openrtb.Imp{
+				"bidderA": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1ParamA":"imp1ValueA"}}`)},
+				},
+			},
+			expectedError: "",
+		},
+		{
+			description: "1 Imp, 2 Bidders",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp1ParamA":"imp1ValueA"},"bidderB":{"imp1ParamB":"imp1ValueB"}}}}`)},
+			},
+			expectedImps: map[string][]openrtb.Imp{
+				"bidderA": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1ParamA":"imp1ValueA"}}`)},
+				},
+				"bidderB": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1ParamB":"imp1ValueB"}}`)},
+				},
+			},
+			expectedError: "",
+		},
+		{
+			description: "2 Imps, 1 Bidders Each",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp1ParamA":"imp1ValueA"}}}}`)},
+				{ID: "imp2", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp2ParamA":"imp2ValueA"}}}}`)},
+			},
+			expectedImps: map[string][]openrtb.Imp{
+				"bidderA": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1ParamA":"imp1ValueA"}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2ParamA":"imp2ValueA"}}`)},
+				},
+			},
+			expectedError: "",
+		},
+		{
+			description: "2 Imps, 2 Bidders Each",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp1paramA":"imp1valueA"},"bidderB":{"imp1paramB":"imp1valueB"}}}}`)},
+				{ID: "imp2", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp2paramA":"imp2valueA"},"bidderB":{"imp2paramB":"imp2valueB"}}}}`)},
+			},
+			expectedImps: map[string][]openrtb.Imp{
+				"bidderA": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1paramA":"imp1valueA"}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2paramA":"imp2valueA"}}`)},
+				},
+				"bidderB": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1paramB":"imp1valueB"}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2paramB":"imp2valueB"}}`)},
+				},
+			},
+			expectedError: "",
+		},
+		{
+			// This is a "happy path" integration test. Functionality is covered in detail by TestCreateSanitizedImpExt.
+			description: "Other Fields - 2 Imps, 2 Bidders Each",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp1paramA":"imp1valueA"},"bidderB":{"imp1paramB":"imp1valueB"}}},"skadn":"imp1SkAdN"}`)},
+				{ID: "imp2", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidderA":{"imp2paramA":"imp2valueA"},"bidderB":{"imp2paramB":"imp2valueB"}}},"skadn":"imp2SkAdN"}`)},
+			},
+			expectedImps: map[string][]openrtb.Imp{
+				"bidderA": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1paramA":"imp1valueA"},"skadn":"imp1SkAdN"}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2paramA":"imp2valueA"},"skadn":"imp2SkAdN"}`)},
+				},
+				"bidderB": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1paramB":"imp1valueB"},"skadn":"imp1SkAdN"}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2paramB":"imp2valueB"},"skadn":"imp2SkAdN"}`)},
+				},
+			},
+			expectedError: "",
+		},
+		{
+			// This is a "happy path" integration test. Functionality is covered in detail by TestExtractBidderExts.
+			description: "Legacy imp.ext.BIDDER - 2 Imps, 2 Bidders Each",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"bidderA":{"imp1paramA":"imp1valueA"},"bidderB":{"imp1paramB":"imp1valueB"}}`)},
+				{ID: "imp2", Ext: json.RawMessage(`{"bidderA":{"imp2paramA":"imp2valueA"},"bidderB":{"imp2paramB":"imp2valueB"}}`)},
+			},
+			expectedImps: map[string][]openrtb.Imp{
+				"bidderA": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1paramA":"imp1valueA"}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2paramA":"imp2valueA"}}`)},
+				},
+				"bidderB": {
+					{ID: "imp1", Ext: json.RawMessage(`{"bidder":{"imp1paramB":"imp1valueB"}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"bidder":{"imp2paramB":"imp2valueB"}}`)},
+				},
+			},
+			expectedError: "",
+		},
+		{
+			description: "Malformed imp.ext",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`malformed`)},
+			},
+			expectedError: "invalid json for imp[0]: invalid character 'm' looking for beginning of value",
+		},
+		{
+			description: "Malformed imp.ext.prebid",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid": malformed}`)},
+			},
+			expectedError: "invalid json for imp[0]: invalid character 'm' looking for beginning of value",
+		},
+		{
+			description: "Malformed imp.ext.prebid.bidder",
+			givenImps: []openrtb.Imp{
+				{ID: "imp1", Ext: json.RawMessage(`{"prebid": {"bidder": malformed}}`)},
+			},
+			expectedError: "invalid json for imp[0]: invalid character 'm' looking for beginning of value",
+		},
+	}
+
+	for _, test := range testCases {
+		imps, err := splitImps(test.givenImps)
+
+		if test.expectedError == "" {
+			assert.NoError(t, err, test.description+":err")
+		} else {
+			assert.EqualError(t, err, test.expectedError, test.description+":err")
+		}
+
+		assert.Equal(t, test.expectedImps, imps, test.description+":imps")
+	}
+}
+
+func TestCreateSanitizedImpExt(t *testing.T) {
+	testCases := []struct {
+		description       string
+		givenImpExt       map[string]json.RawMessage
+		givenImpExtPrebid map[string]json.RawMessage
+		expected          map[string]json.RawMessage
+		expectedError     string
+	}{
+		{
+			description:       "Nil",
+			givenImpExt:       nil,
+			givenImpExtPrebid: nil,
+			expected:          map[string]json.RawMessage{},
+			expectedError:     "",
+		},
+		{
+			description:       "Empty",
+			givenImpExt:       map[string]json.RawMessage{},
+			givenImpExtPrebid: map[string]json.RawMessage{},
+			expected:          map[string]json.RawMessage{},
+			expectedError:     "",
+		},
+		{
+			description: "imp.ext.prebid - Bidders Only",
+			givenImpExt: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"bidder": json.RawMessage(`"anyBidder"`),
+			},
+			expected: map[string]json.RawMessage{
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "imp.ext.prebid - Bidders + Other Values",
+			givenImpExt: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"bidder":    json.RawMessage(`"anyBidder"`),
+				"someOther": json.RawMessage(`"value"`),
+			},
+			expected: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`{"someOther":"value"}`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "imp.ext",
+			givenImpExt: map[string]json.RawMessage{
+				"anyBidder": json.RawMessage(`"anyBidderValues"`),
+				"context":   json.RawMessage(`"anyContext"`),
+				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{},
+			expected: map[string]json.RawMessage{
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "imp.ext + imp.ext.prebid - Prebid Bidders Only",
+			givenImpExt: map[string]json.RawMessage{
+				"anyBidder": json.RawMessage(`"anyBidderValues"`),
+				"prebid":    json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"context":   json.RawMessage(`"anyContext"`),
+				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"bidder": json.RawMessage(`"anyBidder"`),
+			},
+			expected: map[string]json.RawMessage{
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "imp.ext + imp.ext.prebid - Prebid Bidders + Other Values",
+			givenImpExt: map[string]json.RawMessage{
+				"anyBidder": json.RawMessage(`"anyBidderValues"`),
+				"prebid":    json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"context":   json.RawMessage(`"anyContext"`),
+				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"bidder":    json.RawMessage(`"anyBidder"`),
+				"someOther": json.RawMessage(`"value"`),
+			},
+			expected: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`{"someOther":"value"}`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			expectedError: "",
+		},
+		{
+			description: "Marshal Error - imp.ext.prebid",
+			givenImpExt: map[string]json.RawMessage{
+				"prebid":  json.RawMessage(`"ignoredInFavorOfSeparatelyUnmarshalledImpExtPrebid"`),
+				"context": json.RawMessage(`"anyContext"`),
+				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+			},
+			givenImpExtPrebid: map[string]json.RawMessage{
+				"malformed": json.RawMessage(`json`), // String value without quotes.
+			},
+			expected:      nil,
+			expectedError: "cannot marshal ext.prebid: json: error calling MarshalJSON for type json.RawMessage: invalid character 'j' looking for beginning of value",
+		},
+	}
+
+	for _, test := range testCases {
+		result, err := createSanitizedImpExt(test.givenImpExt, test.givenImpExtPrebid)
+
+		if test.expectedError == "" {
+			assert.NoError(t, err, test.description+":err")
+		} else {
+			assert.EqualError(t, err, test.expectedError, test.description+":err")
+		}
+
+		assert.Equal(t, test.expected, result, test.description)
+	}
+}
+
+func TestExtractBidderExts(t *testing.T) {
+	bidderAJSON := json.RawMessage(`{"paramA":"valueA"}}`)
+	bidderBJSON := json.RawMessage(`{"paramB":"valueB"}}`)
+
+	testCases := []struct {
+		description              string
+		givenImpExt              map[string]json.RawMessage
+		givenImpExtPrebidBidders map[string]json.RawMessage
+		expected                 map[string]json.RawMessage
+	}{
+		{
+			description:              "Nil",
+			givenImpExt:              nil,
+			givenImpExtPrebidBidders: nil,
+			expected:                 map[string]json.RawMessage{},
+		},
+		{
+			description:              "Empty",
+			givenImpExt:              map[string]json.RawMessage{},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{},
+			expected:                 map[string]json.RawMessage{},
+		},
+		{
+			description:              "One - imp.ext.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{"bidderA": bidderAJSON},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{},
+			expected:                 map[string]json.RawMessage{"bidderA": bidderAJSON},
+		},
+		{
+			description:              "Many - imp.ext.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{"bidderA": bidderAJSON, "bidderB": bidderBJSON},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{},
+			expected:                 map[string]json.RawMessage{"bidderA": bidderAJSON, "bidderB": bidderBJSON},
+		},
+		{
+			description:              "Special Names Ignored - imp.ext.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`)},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{},
+			expected:                 map[string]json.RawMessage{},
+		},
+		{
+			description:              "One - imp.ext.prebid.bidder.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{"bidderA": bidderAJSON},
+			expected:                 map[string]json.RawMessage{"bidderA": bidderAJSON},
+		},
+		{
+			description:              "Many - imp.ext.prebid.bidder.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{"bidderA": bidderAJSON, "bidderB": bidderBJSON},
+			expected:                 map[string]json.RawMessage{"bidderA": bidderAJSON, "bidderB": bidderBJSON},
+		},
+		{
+			description:              "Special Names Not Treated Differently - imp.ext.prebid.bidder.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`)},
+			expected:                 map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`)},
+		},
+		{
+			description:              "Mixed - Both - imp.ext.BIDDER + imp.ext.prebid.bidder.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{"bidderA": bidderAJSON},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{"bidderB": bidderBJSON},
+			expected:                 map[string]json.RawMessage{"bidderA": bidderAJSON, "bidderB": bidderBJSON},
+		},
+		{
+			description:              "Mixed - Overwrites - imp.ext.BIDDER + imp.ext.prebid.bidder.BIDDER",
+			givenImpExt:              map[string]json.RawMessage{"bidderA": json.RawMessage(`{"shouldBe":"Ignored"}}`)},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{"bidderA": bidderAJSON},
+			expected:                 map[string]json.RawMessage{"bidderA": bidderAJSON},
+		},
+	}
+
+	for _, test := range testCases {
+		result := extractBidderExts(test.givenImpExt, test.givenImpExtPrebidBidders)
+		assert.Equal(t, test.expected, result, test.description)
+	}
+}
+
 func TestCleanOpenRTBRequests(t *testing.T) {
 	testCases := []struct {
 		req              AuctionRequest
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index 79530c86..5b2e8046 100755
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -26,6 +26,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderAdtarget):         syncConfig,
 			string(openrtb_ext.BidderAdtelligent):      syncConfig,
 			string(openrtb_ext.BidderAdvangelists):     syncConfig,
+			string(openrtb_ext.BidderAdyoulike):        syncConfig,
 			string(openrtb_ext.BidderAJA):              syncConfig,
 			string(openrtb_ext.BidderAMX):              syncConfig,
 			string(openrtb_ext.BidderAppnexus):         syncConfig,
@@ -135,31 +136,3 @@ func TestNewSyncerMap(t *testing.T) {
 		}
 	}
 }
-
-// Bidders may have an ID on the IAB-maintained global vendor list.
-// This makes sure that we don't have conflicting IDs among Bidders in our project,
-// since that's almost certainly a bug.
-func TestVendorIDUniqueness(t *testing.T) {
-	cfg := &config.Configuration{}
-	syncers := NewSyncerMap(cfg)
-
-	idMap := make(map[uint16]openrtb_ext.BidderName, len(syncers))
-	for name, syncer := range syncers {
-		id := syncer.GDPRVendorID()
-		if id == 0 {
-			continue
-		}
-
-		if oldName, ok := idMap[id]; ok {
-			t.Errorf("GDPR VendorList ID %d used by both %s and %s. These must be unique.", id, oldName, name)
-		}
-		idMap[id] = name
-	}
-}
-
-func assertStringsMatch(t *testing.T, expected string, actual string) {
-	t.Helper()
-	if expected != actual {
-		t.Errorf("Expected %s, got %s", expected, actual)
-	}
-}