Repository: prebid/prebid-server
Pull request #1249 (2020-04-07 20:22:37)

NinthDecimal Adapter


Patch:
diff --git a/adapters/adgeneration/adgeneration.go b/adapters/adgeneration/adgeneration.go
new file mode 100644
index 00000000..4b1215de
--- /dev/null
+++ b/adapters/adgeneration/adgeneration.go
@@ -0,0 +1,260 @@
+package adgeneration
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+	"regexp"
+	"strconv"
+	"strings"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type AdgenerationAdapter struct {
+	endpoint        string
+	version         string
+	defaultCurrency string
+}
+
+// Server Responses
+type adgServerResponse struct {
+	Locationid string        `json:"locationid"`
+	Dealid     string        `json:"dealid"`
+	Ad         string        `json:"ad"`
+	Beacon     string        `json:"beacon"`
+	Beaconurl  string        `json:"beaconurl"`
+	Cpm        float64       `jsons:"cpm"`
+	Creativeid string        `json:"creativeid"`
+	H          uint64        `json:"h"`
+	W          uint64        `json:"w"`
+	Ttl        uint64        `json:"ttl"`
+	Vastxml    string        `json:"vastxml,omitempty"`
+	LandingUrl string        `json:"landing_url"`
+	Scheduleid string        `json:"scheduleid"`
+	Results    []interface{} `json:"results"`
+}
+
+func (adg *AdgenerationAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	numRequests := len(request.Imp)
+	var errs []error
+
+	if numRequests == 0 {
+		errs = append(errs, &errortypes.BadInput{
+			Message: "No impression in the bid request",
+		})
+		return nil, errs
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+
+	bidRequestArray := make([]*adapters.RequestData, 0, numRequests)
+
+	for index := 0; index < numRequests; index++ {
+		bidRequestUri, err := adg.getRequestUri(request, index)
+		if err != nil {
+			errs = append(errs, err)
+			return nil, errs
+		}
+		bidRequest := &adapters.RequestData{
+			Method:  "GET",
+			Uri:     bidRequestUri,
+			Body:    nil,
+			Headers: headers,
+		}
+		bidRequestArray = append(bidRequestArray, bidRequest)
+	}
+
+	return bidRequestArray, errs
+}
+
+func (adg *AdgenerationAdapter) getRequestUri(request *openrtb.BidRequest, index int) (string, error) {
+	imp := request.Imp[index]
+	adgExt, err := unmarshalExtImpAdgeneration(&imp)
+	if err != nil {
+		return "", &errortypes.BadInput{
+			Message: err.Error(),
+		}
+	}
+	uriObj, err := url.Parse(adg.endpoint)
+	if err != nil {
+		return "", &errortypes.BadInput{
+			Message: err.Error(),
+		}
+	}
+	v := adg.getRawQuery(adgExt.Id, request, &imp)
+	uriObj.RawQuery = v.Encode()
+	return uriObj.String(), err
+}
+
+func (adg *AdgenerationAdapter) getRawQuery(id string, request *openrtb.BidRequest, imp *openrtb.Imp) *url.Values {
+	v := url.Values{}
+	v.Set("posall", "SSPLOC")
+	v.Set("id", id)
+	v.Set("sdktype", "0")
+	v.Set("hb", "true")
+	v.Set("t", "json3")
+	v.Set("currency", adg.getCurrency(request))
+	v.Set("sdkname", "prebidserver")
+	v.Set("adapterver", adg.version)
+	adSize := getSizes(imp)
+	if adSize != "" {
+		v.Set("size", adSize)
+	}
+	if request.Site != nil && request.Site.Page != "" {
+		v.Set("tp", request.Site.Page)
+	}
+	return &v
+}
+
+func unmarshalExtImpAdgeneration(imp *openrtb.Imp) (*openrtb_ext.ExtImpAdgeneration, error) {
+	var bidderExt adapters.ExtImpBidder
+	var adgExt openrtb_ext.ExtImpAdgeneration
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, err
+	}
+	if err := json.Unmarshal(bidderExt.Bidder, &adgExt); err != nil {
+		return nil, err
+	}
+	if adgExt.Id == "" {
+		return nil, errors.New("No Location ID in ExtImpAdgeneration.")
+	}
+	return &adgExt, nil
+}
+
+func getSizes(imp *openrtb.Imp) string {
+	if imp.Banner == nil || len(imp.Banner.Format) == 0 {
+		return ""
+	}
+	var sizeStr string
+	for _, v := range imp.Banner.Format {
+		sizeStr += strconv.FormatUint(v.W, 10) + "×" + strconv.FormatUint(v.H, 10) + ","
+	}
+	if len(sizeStr) > 0 && strings.LastIndex(sizeStr, ",") == len(sizeStr)-1 {
+		sizeStr = sizeStr[:len(sizeStr)-1]
+	}
+	return sizeStr
+}
+
+func (adg *AdgenerationAdapter) getCurrency(request *openrtb.BidRequest) string {
+	if len(request.Cur) <= 0 {
+		return adg.defaultCurrency
+	} else {
+		for _, c := range request.Cur {
+			if adg.defaultCurrency == c {
+				return c
+			}
+		}
+		return request.Cur[0]
+	}
+}
+
+func (adg *AdgenerationAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+	if response.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+	var bidResp adgServerResponse
+	err := json.Unmarshal(response.Body, &bidResp)
+	if err != nil {
+		return nil, []error{err}
+	}
+	if len(bidResp.Results) <= 0 {
+		return nil, nil
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+	var impId string
+	var bitType openrtb_ext.BidType
+	var adm string
+	for _, v := range internalRequest.Imp {
+		adgExt, err := unmarshalExtImpAdgeneration(&v)
+		if err != nil {
+			return nil, []error{&errortypes.BadServerResponse{
+				Message: err.Error(),
+			},
+			}
+		}
+		if adgExt.Id == bidResp.Locationid {
+			impId = v.ID
+			bitType = openrtb_ext.BidTypeBanner
+			adm = createAd(&bidResp, impId)
+			bid := openrtb.Bid{
+				ID:     bidResp.Locationid,
+				ImpID:  impId,
+				AdM:    adm,
+				Price:  bidResp.Cpm,
+				W:      bidResp.W,
+				H:      bidResp.H,
+				CrID:   bidResp.Creativeid,
+				DealID: bidResp.Dealid,
+			}
+
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+				Bid:     &bid,
+				BidType: bitType,
+			})
+			return bidResponse, nil
+		}
+	}
+	return nil, nil
+}
+
+func createAd(body *adgServerResponse, impId string) string {
+	ad := body.Ad
+	if body.Vastxml != "" {
+		ad = "<body><div id=\"apvad-" + impId + "\"></div><script type=\"text/javascript\" id=\"apv\" src=\"https://cdn.apvdr.com/js/VideoAd.min.js\"></script>" + insertVASTMethod(impId, body.Vastxml) + "</body>"
+	}
+	ad = appendChildToBody(ad, body.Beacon)
+	unwrappedAd := removeWrapper(ad)
+	if unwrappedAd != "" {
+		return unwrappedAd
+	}
+	return ad
+}
+
+func insertVASTMethod(bidId string, vastxml string) string {
+	rep := regexp.MustCompile(`/\r?\n/g`)
+	var replacedVastxml = rep.ReplaceAllString(vastxml, "")
+	return "<script type=\"text/javascript\"> (function(){ new APV.VideoAd({s:\"" + bidId + "\"}).load('" + replacedVastxml + "'); })(); </script>"
+}
+
+func appendChildToBody(ad string, data string) string {
+	rep := regexp.MustCompile(`<\/\s?body>`)
+	return rep.ReplaceAllString(ad, data+"</body>")
+}
+
+func removeWrapper(ad string) string {
+	bodyIndex := strings.Index(ad, "<body>")
+	lastBodyIndex := strings.LastIndex(ad, "</body>")
+	if bodyIndex == -1 || lastBodyIndex == -1 {
+		return ""
+	}
+
+	str := strings.TrimSpace(strings.Replace(strings.Replace(ad[bodyIndex:lastBodyIndex], "<body>", "", 1), "</body>", "", 1))
+	return str
+}
+
+func NewAdgenerationAdapter(endpoint string) *AdgenerationAdapter {
+	return &AdgenerationAdapter{
+		endpoint,
+		"1.0.0",
+		"JPY",
+	}
+}
diff --git a/adapters/audienceNetwork/facebook.go b/adapters/audienceNetwork/facebook.go
index db7657f5..9edb9a7d 100644
--- a/adapters/audienceNetwork/facebook.go
+++ b/adapters/audienceNetwork/facebook.go
@@ -130,6 +130,11 @@ func (this *FacebookAdapter) modifyRequest(out *openrtb.BidRequest) error {
 		return err
 	}
 
+	// Every outgoing FAN request has a single impression, so we can safely use the unique
+	// impression ID as the FAN request ID. We need to make sure that we update the request
+	// ID *BEFORE* we generate the auth ID since its a hash based on the request ID
+	out.ID = imp.ID
+
 	reqExt := facebookReqExt{
 		PlatformID: this.platformID,
 		AuthID:     this.makeAuthID(out),
@@ -455,18 +460,39 @@ func NewFacebookBidder(client *http.Client, platformID string, appSecret string)
 }
 
 func (fa *FacebookAdapter) MakeTimeoutNotification(req *adapters.RequestData) (*adapters.RequestData, []error) {
-	// Note, facebook creates one request per imp, so all these requests will only have one imp in them
-	auction_id, err := jsonparser.GetString(req.Body, "imp", "[0]", "id")
+	var (
+		rID   string
+		pubID string
+		err   error
+	)
+
+	// Note, the facebook adserver can only handle single impression requests, so we have to split multi-imp requests into
+	// multiple request. In order to ensure that every split request has a unique ID, the split request IDs are set to the
+	// corresponding imp's ID
+	rID, err = jsonparser.GetString(req.Body, "id")
 	if err != nil {
 		return &adapters.RequestData{}, []error{err}
 	}
 
-	uri := fmt.Sprintf("https://www.facebook.com/audiencenetwork/nurl/?partner=%s&app=%s&auction=%s&ortb_loss_code=2", fa.platformID, fa.platformID, auction_id)
+	// The publisher ID is either in the app object or the site object, depending on the supply of the request so we need
+	// to check both
+	pubID, err = jsonparser.GetString(req.Body, "app", "publisher", "id")
+	if err != nil {
+		pubID, err = jsonparser.GetString(req.Body, "site", "publisher", "id")
+		if err != nil {
+			return &adapters.RequestData{}, []error{
+				errors.New("path [app|site].publisher.id not found in the request"),
+			}
+		}
+	}
+
+	uri := fmt.Sprintf("https://www.facebook.com/audiencenetwork/nurl/?partner=%s&app=%s&auction=%s&ortb_loss_code=2", fa.platformID, pubID, rID)
 	timeoutReq := adapters.RequestData{
 		Method:  "GET",
 		Uri:     uri,
 		Body:    nil,
 		Headers: http.Header{},
 	}
+
 	return &timeoutReq, nil
 }
diff --git a/adapters/beachfront/beachfront.go b/adapters/beachfront/beachfront.go
index e2eb31b3..34a198e9 100644
--- a/adapters/beachfront/beachfront.go
+++ b/adapters/beachfront/beachfront.go
@@ -4,26 +4,27 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/mxmCherry/openrtb"
-	"github.com/prebid/prebid-server/adapters"
-	"github.com/prebid/prebid-server/errortypes"
-	"github.com/prebid/prebid-server/openrtb_ext"
 	"net/http"
 	"reflect"
 	"strconv"
 	"strings"
+
+	"github.com/golang/glog"
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
 const Seat = "beachfront"
 const BidCapacity = 5
 
-const bannerEndpoint = "https://display.bfmio.com/prebid_display"
-const videoEndpoint = "https://reachms.bfmio.com/bid.json?exchange_id"
+const defaultVideoEndpoint = "https://reachms.bfmio.com/bid.json?exchange_id"
 
 const nurlVideoEndpointSuffix = "&prebidserver"
 
 const beachfrontAdapterName = "BF_PREBID_S2S"
-const beachfrontAdapterVersion = "0.8.0"
+const beachfrontAdapterVersion = "0.9.0"
 
 const minBidFloor = 0.01
 
@@ -31,6 +32,12 @@ const DefaultVideoWidth = 300
 const DefaultVideoHeight = 250
 
 type BeachfrontAdapter struct {
+	bannerEndpoint string
+	extraInfo      ExtraInfo
+}
+
+type ExtraInfo struct {
+	VideoEndpoint string `json:"video_endpoint,omitempty"`
 }
 
 type beachfrontRequests struct {
@@ -138,7 +145,7 @@ func (a *BeachfrontAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *a
 		if err == nil {
 			reqs[0] = &adapters.RequestData{
 				Method:  "POST",
-				Uri:     bannerEndpoint,
+				Uri:     a.bannerEndpoint,
 				Body:    bytes,
 				Headers: headers,
 			}
@@ -159,7 +166,7 @@ func (a *BeachfrontAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *a
 		if err == nil {
 			reqs[j+nurlBump] = &adapters.RequestData{
 				Method:  "POST",
-				Uri:     videoEndpoint + "=" + beachfrontRequests.ADMVideo[j].AppId,
+				Uri:     a.extraInfo.VideoEndpoint + "=" + beachfrontRequests.ADMVideo[j].AppId,
 				Body:    bytes,
 				Headers: headers,
 			}
@@ -178,7 +185,7 @@ func (a *BeachfrontAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *a
 			bytes = append([]byte(`{"isPrebid":true,`), bytes[1:]...)
 			reqs[j+admBump] = &adapters.RequestData{
 				Method:  "POST",
-				Uri:     videoEndpoint + "=" + beachfrontRequests.NurlVideo[j].AppId + nurlVideoEndpointSuffix,
+				Uri:     a.extraInfo.VideoEndpoint + "=" + beachfrontRequests.NurlVideo[j].AppId + nurlVideoEndpointSuffix,
 				Body:    bytes,
 				Headers: headers,
 			}
@@ -518,13 +525,13 @@ func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, extern
 
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
 				Bid:      &bids[i],
-				BidType:  getBidType(externalRequest),
+				BidType:  a.getBidType(externalRequest),
 				BidVideo: &impVideo,
 			})
 		} else {
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
 				Bid:     &bids[i],
-				BidType: getBidType(externalRequest),
+				BidType: a.getBidType(externalRequest),
 			})
 		}
 	}
@@ -532,6 +539,15 @@ func (a *BeachfrontAdapter) MakeBids(internalRequest *openrtb.BidRequest, extern
 	return bidResponse, errs
 }
 
+func (a *BeachfrontAdapter) getBidType(externalRequest *adapters.RequestData) openrtb_ext.BidType {
+	t := strings.Split(externalRequest.Uri, "=")[0]
+	if t == a.extraInfo.VideoEndpoint {
+		return openrtb_ext.BidTypeVideo
+	}
+
+	return openrtb_ext.BidTypeBanner
+}
+
 func postprocess(response *adapters.ResponseData, xtrnal openrtb.BidRequest, uri string, id string) ([]openrtb.Bid, []error) {
 	var beachfrontResp []beachfrontResponseSlot
 	var errs = make([]error, 0)
@@ -629,13 +645,13 @@ func getBeachfrontExtension(imp openrtb.Imp) (openrtb_ext.ExtImpBeachfront, erro
 }
 
 func getDomain(page string) string {
-	protoUrl := strings.Split(page, "//")
+	protoURL := strings.Split(page, "//")
 	var domainPage string
 
-	if len(protoUrl) > 1 {
-		domainPage = protoUrl[1]
+	if len(protoURL) > 1 {
+		domainPage = protoURL[1]
 	} else {
-		domainPage = protoUrl[0]
+		domainPage = protoURL[0]
 	}
 
 	return strings.Split(domainPage, "/")[0]
@@ -643,9 +659,9 @@ func getDomain(page string) string {
 }
 
 func isSecure(page string) int8 {
-	protoUrl := strings.Split(page, "://")
+	protoURL := strings.Split(page, "://")
 
-	if len(protoUrl) > 1 && protoUrl[0] == "https" {
+	if len(protoURL) > 1 && protoURL[0] == "https" {
 		return 1
 	}
 
@@ -663,19 +679,25 @@ func getIP(ip string) string {
 	return ip
 }
 
-func getBidType(externalRequest *adapters.RequestData) openrtb_ext.BidType {
-	t := strings.Split(externalRequest.Uri, "=")[0]
-	if t == videoEndpoint {
-		return openrtb_ext.BidTypeVideo
-	}
-
-	return openrtb_ext.BidTypeBanner
-}
-
 func removeVideoElement(slice []beachfrontVideoRequest, s int) []beachfrontVideoRequest {
 	return append(slice[:s], slice[s+1:]...)
 }
 
-func NewBeachfrontBidder() *BeachfrontAdapter {
-	return &BeachfrontAdapter{}
+func NewBeachfrontBidder(bannerEndpoint string, extraAdapterInfo string) adapters.Bidder {
+	var extraInfo ExtraInfo
+
+	if len(extraAdapterInfo) == 0 {
+		extraAdapterInfo = "{\"video_endpoint\":\"" + defaultVideoEndpoint + "\"}"
+	}
+
+	if err := json.Unmarshal([]byte(extraAdapterInfo), &extraInfo); err != nil {
+		glog.Fatal("Invalid Beachfront extra adapter info: " + err.Error())
+		return nil
+	}
+
+	if extraInfo.VideoEndpoint == "" {
+		extraInfo.VideoEndpoint = defaultVideoEndpoint
+	}
+
+	return &BeachfrontAdapter{bannerEndpoint: bannerEndpoint, extraInfo: extraInfo}
 }
diff --git a/adapters/ninthdecimal/ninthdecimal.go b/adapters/ninthdecimal/ninthdecimal.go
new file mode 100755
index 00000000..6d7cbdb6
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimal.go
@@ -0,0 +1,236 @@
+package ninthdecimal
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"text/template"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/macros"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type NinthDecimalAdapter struct {
+	EndpointTemplate template.Template
+}
+
+//MakeRequests prepares request information for prebid-server core
+func (adapter *NinthDecimalAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	errs := make([]error, 0, len(request.Imp))
+	if len(request.Imp) == 0 {
+		errs = append(errs, &errortypes.BadInput{Message: "No impression in the bid request"})
+		return nil, errs
+	}
+	pub2impressions, imps, err := getImpressionsInfo(request.Imp)
+	if len(imps) == 0 {
+		return nil, err
+	}
+	errs = append(errs, err...)
+
+	if len(pub2impressions) == 0 {
+		return nil, errs
+	}
+
+	result := make([]*adapters.RequestData, 0, len(pub2impressions))
+	for k, imps := range pub2impressions {
+		bidRequest, err := adapter.buildAdapterRequest(request, &k, imps)
+		if err != nil {
+			errs = append(errs, err)
+			return nil, errs
+		} else {
+			result = append(result, bidRequest)
+		}
+	}
+	return result, errs
+}
+
+// getImpressionsInfo checks each impression for validity and returns impressions copy with corresponding exts
+func getImpressionsInfo(imps []openrtb.Imp) (map[openrtb_ext.ExtImpNinthDecimal][]openrtb.Imp, []openrtb.Imp, []error) {
+	errors := make([]error, 0, len(imps))
+	resImps := make([]openrtb.Imp, 0, len(imps))
+	res := make(map[openrtb_ext.ExtImpNinthDecimal][]openrtb.Imp)
+
+	for _, imp := range imps {
+		impExt, err := getImpressionExt(&imp)
+		if err != nil {
+			errors = append(errors, err)
+			continue
+		}
+		if err := validateImpression(impExt); err != nil {
+			errors = append(errors, err)
+			continue
+		}
+		//dispatchImpressions
+		//Group impressions by NinthDecimal-specific parameters `pubid
+		if err := compatImpression(&imp); err != nil {
+			errors = append(errors, err)
+			continue
+		}
+		if res[*impExt] == nil {
+			res[*impExt] = make([]openrtb.Imp, 0)
+		}
+		res[*impExt] = append(res[*impExt], imp)
+		resImps = append(resImps, imp)
+	}
+	return res, resImps, errors
+}
+
+func validateImpression(impExt *openrtb_ext.ExtImpNinthDecimal) error {
+	if impExt.PublisherID == "" {
+		return &errortypes.BadInput{Message: "No pubid value provided"}
+	}
+	return nil
+}
+
+//Alter impression info to comply with NinthDecimal platform requirements
+func compatImpression(imp *openrtb.Imp) error {
+	imp.Ext = nil //do not forward ext to NinthDecimal platform
+	if imp.Banner != nil {
+		return compatBannerImpression(imp)
+	}
+	return nil
+}
+
+func compatBannerImpression(imp *openrtb.Imp) error {
+	// Create a copy of the banner, since imp is a shallow copy of the original.
+
+	bannerCopy := *imp.Banner
+	banner := &bannerCopy
+	//As banner.w/h are required fields for NinthDecimal platform - take the first format entry
+	if banner.W == nil || banner.H == nil {
+		if len(banner.Format) == 0 {
+			return &errortypes.BadInput{Message: "Expected at least one banner.format entry or explicit w/h"}
+		}
+		format := banner.Format[0]
+		banner.Format = banner.Format[1:]
+		banner.W = &format.W
+		banner.H = &format.H
+		imp.Banner = banner
+	}
+	return nil
+}
+
+func getImpressionExt(imp *openrtb.Imp) (*openrtb_ext.ExtImpNinthDecimal, error) {
+	var bidderExt adapters.ExtImpBidder
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: err.Error(),
+		}
+	}
+	var NinthDecimalExt openrtb_ext.ExtImpNinthDecimal
+	if err := json.Unmarshal(bidderExt.Bidder, &NinthDecimalExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: err.Error(),
+		}
+	}
+	return &NinthDecimalExt, nil
+}
+
+func (adapter *NinthDecimalAdapter) buildAdapterRequest(prebidBidRequest *openrtb.BidRequest, params *openrtb_ext.ExtImpNinthDecimal, imps []openrtb.Imp) (*adapters.RequestData, error) {
+	newBidRequest := createBidRequest(prebidBidRequest, params, imps)
+	reqJSON, err := json.Marshal(newBidRequest)
+	if err != nil {
+		return nil, err
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("x-openrtb-version", "2.5")
+
+	url, err := adapter.buildEndpointURL(params)
+	if err != nil {
+		return nil, err
+	}
+
+	return &adapters.RequestData{
+		Method:  "POST",
+		Uri:     url,
+		Body:    reqJSON,
+		Headers: headers}, nil
+}
+
+func createBidRequest(prebidBidRequest *openrtb.BidRequest, params *openrtb_ext.ExtImpNinthDecimal, imps []openrtb.Imp) *openrtb.BidRequest {
+	bidRequest := *prebidBidRequest
+	bidRequest.Imp = imps
+	for idx := range bidRequest.Imp {
+		imp := &bidRequest.Imp[idx]
+		imp.TagID = params.Placement
+	}
+	if bidRequest.Site != nil {
+		// Need to copy Site as Request is a shallow copy
+		siteCopy := *bidRequest.Site
+		bidRequest.Site = &siteCopy
+		bidRequest.Site.Publisher = nil
+		bidRequest.Site.Domain = ""
+	}
+	if bidRequest.App != nil {
+		// Need to copy App as Request is a shallow copy
+		appCopy := *bidRequest.App
+		bidRequest.App = &appCopy
+		bidRequest.App.Publisher = nil
+	}
+	return &bidRequest
+}
+
+// Builds enpoint url based on adapter-specific pub settings from imp.ext
+func (adapter *NinthDecimalAdapter) buildEndpointURL(params *openrtb_ext.ExtImpNinthDecimal) (string, error) {
+	endpointParams := macros.EndpointTemplateParams{PublisherID: params.PublisherID}
+	return macros.ResolveMacros(adapter.EndpointTemplate, endpointParams)
+}
+
+//MakeBids translates NinthDecimal bid response to prebid-server specific format
+func (adapter *NinthDecimalAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var msg = ""
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+	if response.StatusCode != http.StatusOK {
+		msg = fmt.Sprintf("Unexpected http status code: %d", response.StatusCode)
+		return nil, []error{&errortypes.BadServerResponse{Message: msg}}
+
+	}
+	var bidResp openrtb.BidResponse
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		msg = fmt.Sprintf("Bad server response: %d", err)
+		return nil, []error{&errortypes.BadServerResponse{Message: msg}}
+	}
+	if len(bidResp.SeatBid) != 1 {
+		var msg = fmt.Sprintf("Invalid SeatBids count: %d", len(bidResp.SeatBid))
+		return nil, []error{&errortypes.BadServerResponse{Message: msg}}
+	}
+
+	seatBid := bidResp.SeatBid[0]
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid))
+
+	for i := 0; i < len(seatBid.Bid); i++ {
+		bid := seatBid.Bid[i]
+		bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+			Bid:     &bid,
+			BidType: getMediaTypeForImpID(bid.ImpID, internalRequest.Imp),
+		})
+	}
+	return bidResponse, nil
+}
+
+// getMediaTypeForImp figures out which media type this bid is for
+func getMediaTypeForImpID(impID string, imps []openrtb.Imp) openrtb_ext.BidType {
+	for _, imp := range imps {
+		if imp.ID == impID && imp.Video != nil {
+			return openrtb_ext.BidTypeVideo
+		}
+	}
+	return openrtb_ext.BidTypeBanner
+}
+
+// NewNinthDecimalAdapter to be called in prebid-server core to create NinthDecimal adapter instance
+func NewNinthDecimalBidder(endpointTemplate string) adapters.Bidder {
+	template, err := template.New("endpointTemplate").Parse(endpointTemplate)
+	if err != nil {
+		return nil
+	}
+	return &NinthDecimalAdapter{EndpointTemplate: *template}
+}
diff --git a/adapters/ninthdecimal/usersync.go b/adapters/ninthdecimal/usersync.go
new file mode 100755
index 00000000..7a8d029c
--- /dev/null
+++ b/adapters/ninthdecimal/usersync.go
@@ -0,0 +1,12 @@
+package ninthdecimal
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewNinthDecimalSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("ninthdecimal", 0, temp, adapters.SyncTypeIframe)
+}
diff --git a/adapters/rubicon/rubicon.go b/adapters/rubicon/rubicon.go
index 46caf262..dad85ee1 100644
--- a/adapters/rubicon/rubicon.go
+++ b/adapters/rubicon/rubicon.go
@@ -21,6 +21,8 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
+const badvLimitSize = 50
+
 type RubiconAdapter struct {
 	http         *adapters.HTTPAdapter
 	URI          string
@@ -740,6 +742,13 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adap
 			request.App = &appCopy
 		}
 
+		reqBadv := request.BAdv
+		if reqBadv != nil {
+			if len(reqBadv) > badvLimitSize {
+				request.BAdv = reqBadv[:badvLimitSize]
+			}
+		}
+
 		request.Imp = []openrtb.Imp{thisImp}
 		request.Cur = nil
 		request.Ext = nil
diff --git a/adapters/telaria/telaria.go b/adapters/telaria/telaria.go
new file mode 100644
index 00000000..9edafa86
--- /dev/null
+++ b/adapters/telaria/telaria.go
@@ -0,0 +1,330 @@
+package telaria
+
+import (
+	"bytes"
+	"compress/gzip"
+	"encoding/json"
+	"fmt"
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"net/http"
+	"strconv"
+)
+
+const Endpoint = "https://ads.tremorhub.com/ad/rtb/prebid"
+
+type TelariaAdapter struct {
+	URI string
+}
+
+// This will be part of Imp[i].Ext when this adapter calls out the Telaria Ad Server
+type ImpressionExtOut struct {
+	OriginalTagID       string `json:"originalTagid"`
+	OriginalPublisherID string `json:"originalPublisherid"`
+}
+
+// used for cookies and such
+func (a *TelariaAdapter) Name() string {
+	return "telaria"
+}
+
+func (a *TelariaAdapter) SkipNoCookies() bool {
+	return false
+}
+
+// Endpoint for Telaria Ad server
+func (a *TelariaAdapter) FetchEndpoint() string {
+	return a.URI
+}
+
+// Checker method to ensure len(request.Imp) > 0
+func (a *TelariaAdapter) CheckHasImps(request *openrtb.BidRequest) error {
+	if len(request.Imp) == 0 {
+		err := &errortypes.BadInput{
+			Message: "Telaria: Missing Imp Object",
+		}
+		return err
+	}
+	return nil
+}
+
+// Checking if Imp[i].Video exists and Imp[i].Banner doesn't exist
+func (a *TelariaAdapter) CheckHasVideoObject(request *openrtb.BidRequest) error {
+	hasVideoObject := false
+
+	for _, imp := range request.Imp {
+		if imp.Banner != nil {
+			return &errortypes.BadInput{
+				Message: "Telaria: Banner not supported",
+			}
+		}
+
+		hasVideoObject = hasVideoObject || imp.Video != nil
+	}
+
+	if !hasVideoObject {
+		return &errortypes.BadInput{
+			Message: "Telaria: Only Supports Video",
+		}
+	}
+
+	return nil
+}
+
+// Fetches the populated header object
+func GetHeaders(request *openrtb.BidRequest) *http.Header {
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("X-Openrtb-Version", "2.5")
+	headers.Add("Accept-Encoding", "gzip")
+
+	if request.Device != nil {
+		if len(request.Device.UA) > 0 {
+			headers.Add("User-Agent", request.Device.UA)
+		}
+
+		if len(request.Device.IP) > 0 {
+			headers.Add("X-Forwarded-For", request.Device.IP)
+		}
+
+		if len(request.Device.Language) > 0 {
+			headers.Add("Accept-Language", request.Device.Language)
+		}
+
+		if request.Device.DNT != nil {
+			headers.Add("Dnt", strconv.Itoa(int(*request.Device.DNT)))
+		}
+	}
+
+	return &headers
+}
+
+// Checks the imp[i].ext object and returns a imp.ext object as per ExtImpTelaria format
+func (a *TelariaAdapter) FetchTelariaExtImpParams(imp *openrtb.Imp) (*openrtb_ext.ExtImpTelaria, error) {
+	var bidderExt adapters.ExtImpBidder
+	err := json.Unmarshal(imp.Ext, &bidderExt)
+
+	if err != nil {
+		err = &errortypes.BadInput{
+			Message: "Telaria: ext.bidder not provided",
+		}
+
+		return nil, err
+	}
+
+	var telariaExt openrtb_ext.ExtImpTelaria
+	err = json.Unmarshal(bidderExt.Bidder, &telariaExt)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if telariaExt.SeatCode == "" {
+		return nil, &errortypes.BadInput{Message: "Telaria: Seat Code required"}
+	}
+
+	return &telariaExt, nil
+}
+
+// Method to fetch the original publisher ID. Note that this method must be called
+// before we replace publisher.ID with seatCode
+func (a *TelariaAdapter) FetchOriginalPublisherID(request *openrtb.BidRequest) string {
+
+	if request.Site != nil && request.Site.Publisher != nil {
+		return request.Site.Publisher.ID
+	} else if request.App != nil && request.App.Publisher != nil {
+		return request.App.Publisher.ID
+	}
+
+	return ""
+}
+
+// Method to do a deep copy of the publisher object. It also adds the seatCode as publisher.ID
+func (a *TelariaAdapter) MakePublisherObject(seatCode string, publisher *openrtb.Publisher) *openrtb.Publisher {
+	var pub = &openrtb.Publisher{ID: seatCode}
+
+	if publisher != nil {
+		pub.Domain = publisher.Domain
+		pub.Name = publisher.Name
+		pub.Cat = publisher.Cat
+		pub.Ext = publisher.Ext
+	}
+
+	return pub
+}
+
+// This method changes <site/app>.publisher.id to the seatCode
+func (a *TelariaAdapter) PopulatePublisherId(request *openrtb.BidRequest, seatCode string) (*openrtb.Site, *openrtb.App) {
+	if request.Site != nil {
+		siteCopy := *request.Site
+		siteCopy.Publisher = a.MakePublisherObject(seatCode, request.Site.Publisher)
+		return &siteCopy, nil
+	} else if request.App != nil {
+		appCopy := *request.App
+		appCopy.Publisher = a.MakePublisherObject(seatCode, request.App.Publisher)
+		return nil, &appCopy
+	}
+	return nil, nil
+}
+
+func (a *TelariaAdapter) MakeRequests(requestIn *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+
+	// make a copy of the incoming request
+	request := *requestIn
+
+	// ensure that the request has Impressions
+	if noImps := a.CheckHasImps(&request); noImps != nil {
+		return nil, []error{noImps}
+	}
+
+	// ensure that the request has a Video object
+	if noVideoObjectError := a.CheckHasVideoObject(&request); noVideoObjectError != nil {
+		return nil, []error{noVideoObjectError}
+	}
+
+	var seatCode string
+	originalPublisherID := a.FetchOriginalPublisherID(&request)
+
+	var errors []error
+	for i, imp := range request.Imp {
+		// fetch adCode & seatCode from Imp[i].Ext
+		telariaExt, err := a.FetchTelariaExtImpParams(&imp)
+		if err != nil {
+			errors = append(errors, err)
+			break
+		}
+
+		seatCode = telariaExt.SeatCode
+
+		// move the original tagId and the original publisher.id into the Imp[i].Ext object
+		request.Imp[i].Ext, err = json.Marshal(&ImpressionExtOut{request.Imp[i].TagID, originalPublisherID})
+		if err != nil {
+			errors = append(errors, err)
+			break
+		}
+
+		// Swap the tagID with adCode
+		request.Imp[i].TagID = telariaExt.AdCode
+	}
+
+	if len(errors) > 0 {
+		return nil, errors
+	}
+
+	// Add seatCode to <Site/App>.Publisher.ID
+	siteObject, appObject := a.PopulatePublisherId(&request, seatCode)
+
+	request.Site = siteObject
+	request.App = appObject
+
+	reqJSON, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	return []*adapters.RequestData{{
+		Method:  "POST",
+		Uri:     a.FetchEndpoint(),
+		Body:    reqJSON,
+		Headers: *GetHeaders(&request),
+	}}, nil
+}
+
+// response isn't automatically decompressed. This method unzips the response if Content-Encoding is gzip
+func GetResponseBody(response *adapters.ResponseData) ([]byte, error) {
+
+	if "gzip" == response.Headers.Get("Content-Encoding") {
+		body := bytes.NewBuffer(response.Body)
+		r, readerErr := gzip.NewReader(body)
+		if readerErr != nil {
+			return nil, &errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Error while trying to unzip data [ %d ]", response.StatusCode),
+			}
+		}
+		var resB bytes.Buffer
+		var err error
+		_, err = resB.ReadFrom(r)
+		if err != nil {
+			return nil, &errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Error while trying to unzip data [ %d ]", response.StatusCode),
+			}
+		}
+
+		response.Headers.Del("Content-Encoding")
+
+		return resB.Bytes(), nil
+	} else {
+		return response.Body, nil
+	}
+}
+
+func (a *TelariaAdapter) CheckResponseStatusCodes(response *adapters.ResponseData) error {
+	if response.StatusCode == http.StatusNoContent {
+		return &errortypes.BadInput{Message: "Telaria: Invalid Bid Request received by the server"}
+	}
+
+	if response.StatusCode == http.StatusBadRequest {
+		return &errortypes.BadInput{
+			Message: fmt.Sprintf("Telaria: Unexpected status code: [ %d ] ", response.StatusCode),
+		}
+	}
+
+	if response.StatusCode == http.StatusServiceUnavailable {
+		return &errortypes.BadInput{
+			Message: fmt.Sprintf("Telaria: Something went wrong, please contact your Account Manager. Status Code: [ %d ] ", response.StatusCode),
+		}
+	}
+
+	if response.StatusCode < http.StatusOK || response.StatusCode >= http.StatusMultipleChoices {
+		return &errortypes.BadInput{
+			Message: fmt.Sprintf("Telaria: Something went wrong, please contact your Account Manager. Status Code: [ %d ] ", response.StatusCode),
+		}
+	}
+
+	return nil
+}
+
+func (a *TelariaAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+
+	httpStatusError := a.CheckResponseStatusCodes(response)
+	if httpStatusError != nil {
+		return nil, []error{httpStatusError}
+	}
+
+	responseBody, err := GetResponseBody(response)
+
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	var bidResp openrtb.BidResponse
+	if err := json.Unmarshal(responseBody, &bidResp); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Telaria: Bad Server Response",
+		}}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid))
+	sb := bidResp.SeatBid[0]
+
+	for _, bid := range sb.Bid {
+		bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+			Bid:     &bid,
+			BidType: openrtb_ext.BidTypeVideo,
+		})
+	}
+	return bidResponse, nil
+}
+
+func NewTelariaBidder(endpoint string) *TelariaAdapter {
+	if endpoint == "" {
+		endpoint = Endpoint
+	}
+
+	return &TelariaAdapter{
+		URI: endpoint,
+	}
+}
diff --git a/adapters/telaria/usersync.go b/adapters/telaria/usersync.go
new file mode 100644
index 00000000..e3f76f6e
--- /dev/null
+++ b/adapters/telaria/usersync.go
@@ -0,0 +1,12 @@
+package telaria
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewTelariaSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("telaria", 202, temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/yieldone/usersync.go b/adapters/yieldone/usersync.go
new file mode 100644
index 00000000..bc9d1b32
--- /dev/null
+++ b/adapters/yieldone/usersync.go
@@ -0,0 +1,12 @@
+package yieldone
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewYieldoneSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("yieldone", 0, temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/yieldone/yieldone.go b/adapters/yieldone/yieldone.go
new file mode 100644
index 00000000..f02d1a0b
--- /dev/null
+++ b/adapters/yieldone/yieldone.go
@@ -0,0 +1,144 @@
+package yieldone
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type YieldoneAdapter struct {
+	endpoint string
+}
+
+// MakeRequests makes the HTTP requests which should be made to fetch bids.
+func (a *YieldoneAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var errors = make([]error, 0)
+
+	var validImps []openrtb.Imp
+	for i := 0; i < len(request.Imp); i++ {
+		if err := preprocess(&request.Imp[i]); err == nil {
+			validImps = append(validImps, request.Imp[i])
+		} else {
+			errors = append(errors, err)
+		}
+	}
+
+	request.Imp = validImps
+
+	reqJSON, err := json.Marshal(request)
+	if err != nil {
+		errors = append(errors, err)
+		return nil, errors
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+
+	return []*adapters.RequestData{{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    reqJSON,
+		Headers: headers,
+	}}, errors
+}
+
+// MakeBids unpacks the server's response into Bids.
+func (a *YieldoneAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if response.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	var bidResp openrtb.BidResponse
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+
+	for _, sb := range bidResp.SeatBid {
+		for i := range sb.Bid {
+			bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp)
+			if err != nil {
+				return nil, []error{err}
+			}
+
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+				Bid:     &sb.Bid[i],
+				BidType: bidType,
+			})
+		}
+	}
+	return bidResponse, nil
+
+}
+
+// NewYieldoneBidder configure bidder endpoint
+func NewYieldoneBidder(endpoint string) *YieldoneAdapter {
+	return &YieldoneAdapter{
+		endpoint: endpoint,
+	}
+}
+
+func preprocess(imp *openrtb.Imp) error {
+
+	var ext adapters.ExtImpBidder
+	if err := json.Unmarshal(imp.Ext, &ext); err != nil {
+		return err
+	}
+	var impressionExt openrtb_ext.ExtImpYieldone
+	if err := json.Unmarshal(ext.Bidder, &impressionExt); err != nil {
+		return err
+	}
+
+	if imp.Banner != nil {
+		bannerCopy := *imp.Banner
+		if bannerCopy.W == nil && bannerCopy.H == nil && len(bannerCopy.Format) > 0 {
+			firstFormat := bannerCopy.Format[0]
+			bannerCopy.W = &(firstFormat.W)
+			bannerCopy.H = &(firstFormat.H)
+		}
+		imp.Banner = &bannerCopy
+	}
+
+	return nil
+}
+
+func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType, error) {
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner != nil {
+				return openrtb_ext.BidTypeBanner, nil
+			}
+
+			if imp.Video != nil {
+				return openrtb_ext.BidTypeVideo, nil
+			}
+
+			return "", &errortypes.BadServerResponse{
+				Message: fmt.Sprintf("Unknown impression type for ID: \"%s\"", impID),
+			}
+		}
+	}
+
+	// This shouldnt happen. Lets handle it just incase by returning an error.
+	return "", &errortypes.BadServerResponse{
+		Message: fmt.Sprintf("Failed to find impression for ID: \"%s\"", impID),
+	}
+}
diff --git a/config/config.go b/config/config.go
old mode 100644
new mode 100755
index 2cb5f8f2..02745bbb
--- a/config/config.go
+++ b/config/config.go
@@ -494,6 +494,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	externalURL := cfg.ExternalURL
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.Bidder33Across, "https://ic.tynt.com/r/d?m=xch&rt=html&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&ru="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3D33across%26uid%3D33XUSERID33X&id=zzz000000000002zzz")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdform, "https://cm.adform.net/cookie?redirect_url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadform%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	// openrtb_ext.BidderAdgeneration doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdkernel, "https://sync.adkernel.com/user-sync?t=image&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadkernel%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdkernelAdn, "https://tag.adkernel.com/syncr?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3DadkernelAdn%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdpone, "https://usersync.adpone.com/csync?redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadpone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Buid%7D")
@@ -509,7 +510,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDatablocks, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEmxDigital, "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEngageBDR, "https://match.bnmla.com/usersync/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")
-	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEPlanning, "https://ads.us.e-planning.net/uspd/1/?du=https%3A%2F%2Fads.us.e-planning.net%2Fgetuid%2F1%2F5a1ad71d2d53a0f5%3F"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Deplanning%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEPlanning, "https://ads.us.e-planning.net/uspd/1/?du="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Deplanning%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	// openrtb_ext.BidderFacebook doesn't have a good default.
 	// openrtb_ext.BidderGamma doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGamoshi, "https://rtb.gamoshi.io/user_sync_prebid?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgamoshi%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bgusr%5D")
@@ -522,6 +523,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMarsmedia, "https://dmp.rtbsrv.com/dmp/profiles/cm?p_id=179&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmarsmedia%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMgid, "https://cm.mgid.com/m?cdsp=363893&adu="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmgid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Bmuidn%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNanoInteractive, "https://ad.audiencemanager.de/hbs/cookie_sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dnanointeractive%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNinthDecimal, "https://rtb.ninthdecimal.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dninthdecimal%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderOpenx, "https://rtb.openx.net/sync/prebid?r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dopenx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPubmatic, "https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&predirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPulsepoint, "https://bh.contextweb.com/rtset?pid=561205&ev=1&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpulsepoint%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25VGUID%25%25")
@@ -535,6 +537,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSovrn, "https://ap.lijit.com/pixel?redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsovrn%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderSynacormedia, "https://sync.technoratimedia.com/services?srv=cs&pid=70&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dsynacormedia%26uid%3D%5BUSER_ID%5D")
 	// openrtb_ext.BidderTappx doesn't have a good default.
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTelaria, "https://pbs.publishers.tremorhub.com/pubsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dtelaria%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Btvid%5D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTriplelift, "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dtriplelift%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTripleliftNative, "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dtriplelift_native%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderUcfunnel, "https://sync.aralego.com/idsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&usprivacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ducfunnel%26uid%3DSspCookieUserId")
@@ -543,6 +546,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderVisx, "https://t.visx.net/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")
 	// openrtb_ext.BidderVrtcal doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldmo, "https://ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldone, "https://y.one.impact-ad.jp/hbs_sc?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderZeroClickFraud, "https://s.0cf.io/sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dzeroclickfraud%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D")
 }
 
@@ -683,6 +687,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.33across.endpoint", "http://ssc.33across.com/api/v1/hb")
 	v.SetDefault("adapters.33across.partner_id", "")
 	v.SetDefault("adapters.adform.endpoint", "http://adx.adform.net/adx")
+	v.SetDefault("adapters.adgeneration.endpoint", "https://d.socdm.com/adsv/v1")
 	v.SetDefault("adapters.adkernel.endpoint", "http://{{.Host}}/hb?zone={{.ZoneID}}")
 	v.SetDefault("adapters.adkerneladn.endpoint", "http://{{.Host}}/rtbpub?account={{.PublisherID}}")
 	v.SetDefault("adapters.admixer.endpoint", "http://inv-nets.admixer.net/pbs.aspx")
@@ -694,6 +699,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.appnexus.endpoint", "http://ib.adnxs.com/openrtb2") // Docs: https://wiki.appnexus.com/display/supply/Incoming+Bid+Request+from+SSPs
 	v.SetDefault("adapters.appnexus.platform_id", "5")
 	v.SetDefault("adapters.beachfront.endpoint", "https://display.bfmio.com/prebid_display")
+	v.SetDefault("adapters.beachfront.extra_info", "{\"video_endpoint\":\"https://reachms.bfmio.com/bid.json?exchange_id\"}")
 	v.SetDefault("adapters.brightroll.endpoint", "http://east-bid.ybp.yahoo.com/bid/appnexuspbs")
 	v.SetDefault("adapters.consumable.endpoint", "https://e.serverbid.com/api/v2")
 	v.SetDefault("adapters.conversant.endpoint", "http://api.hb.ad.cpe.dotomi.com/s2s/header/24")
@@ -715,6 +721,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.marsmedia.endpoint", "https://bid306.rtbsrv.com/bidder/?bid=f3xtet")
 	v.SetDefault("adapters.mgid.endpoint", "https://prebid.mgid.com/prebid/")
 	v.SetDefault("adapters.nanointeractive.endpoint", "https://ad.audiencemanager.de/hbs")
+	v.SetDefault("adapters.ninthdecimal.endpoint", "http://rtb.ninthdecimal.com/xp/get?pubid={{.PublisherID}}")
 	v.SetDefault("adapters.openx.endpoint", "http://rtb.openx.net/prebid")
 	v.SetDefault("adapters.pubmatic.endpoint", "https://hbopenbid.pubmatic.com/translator?source=prebid-server")
 	v.SetDefault("adapters.pubnative.endpoint", "http://dsp.pubnative.net/bid/v1/request")
@@ -729,6 +736,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.sovrn.endpoint", "http://ap.lijit.com/rtb/bid?src=prebid_server")
 	v.SetDefault("adapters.synacormedia.endpoint", "http://{{.Host}}.technoratimedia.com/openrtb/bids/{{.Host}}")
 	v.SetDefault("adapters.tappx.endpoint", "https://{{.Host}}")
+	v.SetDefault("adapters.telaria.endpoint", "https://ads.tremorhub.com/ad/rtb/prebid")
 	v.SetDefault("adapters.triplelift_native.disabled", true)
 	v.SetDefault("adapters.triplelift_native.extra_info", "{\"publisher_whitelist\":[]}")
 	v.SetDefault("adapters.triplelift.endpoint", "https://tlx.3lift.com/s2s/auction?supplier_id=20")
@@ -739,6 +747,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.visx.endpoint", "https://t.visx.net/s2s_bid?wrapperType=s2s_prebid_standard")
 	v.SetDefault("adapters.vrtcal.endpoint", "http://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804")
 	v.SetDefault("adapters.yieldmo.endpoint", "https://ads.yieldmo.com/exchange/prebid-server")
+	v.SetDefault("adapters.yieldone.endpoint", "https://y.one.impact-ad.jp/hbs_imp")
 	v.SetDefault("adapters.zeroclickfraud.endpoint", "http://{{.Host}}/openrtb2?sid={{.SourceId}}")
 
 	v.SetDefault("max_request_size", 1024*256)
diff --git a/docs/bidders/kidoz.md b/docs/bidders/kidoz.md
new file mode 100644
index 00000000..433dd71c
--- /dev/null
+++ b/docs/bidders/kidoz.md
@@ -0,0 +1,9 @@
+# Kidoz Bidder
+
+Kidoz is exclusively for Mobile app COPPA compatible ads, 100% kid relevant and appropriate.
+
+In order for a company to receive bids from Kidoz, they must first open a publisher account at Kidoz.net
+(https://accounts.kidoz.net/publishers/register) and accept the Kidoz Terms and Conditions and Privacy Policy. 
+Kidoz publishers must confirm that all of their content properties are COPPA and GDPR compliant and perform no monitoring
+or tracking of U13 users in their operations.  New publishers are provided a Publisher ID and AccessToken, this can also
+be used to login to their dashboard at the Kidoz.net portal to monitor their account activity. 
diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go
index 0215eb4c..c7316604 100644
--- a/endpoints/openrtb2/video_auction.go
+++ b/endpoints/openrtb2/video_auction.go
@@ -8,12 +8,13 @@ import (
 	"io"
 	"io/ioutil"
 	"net/http"
+	"net/url"
 	"strconv"
 	"strings"
 	"time"
 
 	"github.com/buger/jsonparser"
-	jsonpatch "github.com/evanphx/json-patch"
+	"github.com/evanphx/json-patch"
 	"github.com/gofrs/uuid"
 	"github.com/prebid/prebid-server/errortypes"
 
@@ -617,7 +618,18 @@ func (deps *endpointDeps) parseVideoRequest(request []byte, headers http.Header)
 
 	//if Device.UA is not present in request body, init it with user-agent from request header if it's present
 	if req.Device.UA == "" {
-		req.Device.UA = headers.Get("User-Agent")
+		ua := headers.Get("User-Agent")
+
+		//Check UA is encoded. Without it the `+` character would get changed to a space if not actually encoded
+		if strings.ContainsAny(ua, "%") {
+			var err error
+			req.Device.UA, err = url.QueryUnescape(ua)
+			if err != nil {
+				req.Device.UA = ua
+			}
+		} else {
+			req.Device.UA = ua
+		}
 	}
 
 	errL, podErrors := deps.validateVideoRequest(req)
diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go
old mode 100644
new mode 100755
index f7b970c5..0b0c42d8
--- a/exchange/adapter_map.go
+++ b/exchange/adapter_map.go
@@ -8,6 +8,7 @@ import (
 	"github.com/prebid/prebid-server/adapters"
 	ttx "github.com/prebid/prebid-server/adapters/33across"
 	"github.com/prebid/prebid-server/adapters/adform"
+	"github.com/prebid/prebid-server/adapters/adgeneration"
 	"github.com/prebid/prebid-server/adapters/adkernel"
 	"github.com/prebid/prebid-server/adapters/adkernelAdn"
 	"github.com/prebid/prebid-server/adapters/admixer"
@@ -40,6 +41,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/marsmedia"
 	"github.com/prebid/prebid-server/adapters/mgid"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
+	"github.com/prebid/prebid-server/adapters/ninthdecimal"
 	"github.com/prebid/prebid-server/adapters/openx"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
 	"github.com/prebid/prebid-server/adapters/pubnative"
@@ -54,6 +56,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/sovrn"
 	"github.com/prebid/prebid-server/adapters/synacormedia"
 	"github.com/prebid/prebid-server/adapters/tappx"
+	"github.com/prebid/prebid-server/adapters/telaria"
 	"github.com/prebid/prebid-server/adapters/triplelift"
 	"github.com/prebid/prebid-server/adapters/triplelift_native"
 	"github.com/prebid/prebid-server/adapters/ucfunnel"
@@ -63,6 +66,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/visx"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
 	"github.com/prebid/prebid-server/adapters/yieldmo"
+	"github.com/prebid/prebid-server/adapters/yieldone"
 	"github.com/prebid/prebid-server/adapters/zeroclickfraud"
 	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/openrtb_ext"
@@ -75,6 +79,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 	ortbBidders := map[openrtb_ext.BidderName]adapters.Bidder{
 		openrtb_ext.Bidder33Across:     ttx.New33AcrossBidder(cfg.Adapters[string(openrtb_ext.Bidder33Across)].Endpoint),
 		openrtb_ext.BidderAdform:       adform.NewAdformBidder(client, cfg.Adapters[string(openrtb_ext.BidderAdform)].Endpoint),
+		openrtb_ext.BidderAdgeneration: adgeneration.NewAdgenerationAdapter(cfg.Adapters[string(openrtb_ext.BidderAdgeneration)].Endpoint),
 		openrtb_ext.BidderAdkernel:     adkernel.NewAdkernelAdapter(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdkernel))].Endpoint),
 		openrtb_ext.BidderAdkernelAdn:  adkernelAdn.NewAdkernelAdnAdapter(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdkernelAdn))].Endpoint),
 		openrtb_ext.BidderAdmixer:      admixer.NewAdmixerBidder(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdmixer))].Endpoint),
@@ -84,15 +89,14 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderAdvangelists: advangelists.NewAdvangelistsBidder(cfg.Adapters[string(openrtb_ext.BidderAdvangelists)].Endpoint),
 		openrtb_ext.BidderApplogy:      applogy.NewApplogyBidder(cfg.Adapters[string(openrtb_ext.BidderApplogy)].Endpoint),
 		openrtb_ext.BidderAppnexus:     appnexus.NewAppNexusBidder(client, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].PlatformID),
-		// TODO #615: Update the config setup so that the Beachfront URLs can be configured, and use those in TestRaceIntegration in exchange_test.go
-		openrtb_ext.BidderBeachfront: beachfront.NewBeachfrontBidder(),
-		openrtb_ext.BidderBrightroll: brightroll.NewBrightrollBidder(cfg.Adapters[string(openrtb_ext.BidderBrightroll)].Endpoint),
-		openrtb_ext.BidderConsumable: consumable.NewConsumableBidder(cfg.Adapters[string(openrtb_ext.BidderConsumable)].Endpoint),
-		openrtb_ext.BidderCpmstar:    cpmstar.NewCpmstarBidder(cfg.Adapters[string(openrtb_ext.BidderCpmstar)].Endpoint),
-		openrtb_ext.BidderDatablocks: datablocks.NewDatablocksBidder(cfg.Adapters[string(openrtb_ext.BidderDatablocks)].Endpoint),
-		openrtb_ext.BidderEmxDigital: emx_digital.NewEmxDigitalBidder(cfg.Adapters[string(openrtb_ext.BidderEmxDigital)].Endpoint),
-		openrtb_ext.BidderEngageBDR:  engagebdr.NewEngageBDRBidder(client, cfg.Adapters[string(openrtb_ext.BidderEngageBDR)].Endpoint),
-		openrtb_ext.BidderEPlanning:  eplanning.NewEPlanningBidder(client, cfg.Adapters[string(openrtb_ext.BidderEPlanning)].Endpoint),
+		openrtb_ext.BidderBeachfront:   beachfront.NewBeachfrontBidder(cfg.Adapters[string(openrtb_ext.BidderBeachfront)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderBeachfront)].ExtraAdapterInfo),
+		openrtb_ext.BidderBrightroll:   brightroll.NewBrightrollBidder(cfg.Adapters[string(openrtb_ext.BidderBrightroll)].Endpoint),
+		openrtb_ext.BidderConsumable:   consumable.NewConsumableBidder(cfg.Adapters[string(openrtb_ext.BidderConsumable)].Endpoint),
+		openrtb_ext.BidderCpmstar:      cpmstar.NewCpmstarBidder(cfg.Adapters[string(openrtb_ext.BidderCpmstar)].Endpoint),
+		openrtb_ext.BidderDatablocks:   datablocks.NewDatablocksBidder(cfg.Adapters[string(openrtb_ext.BidderDatablocks)].Endpoint),
+		openrtb_ext.BidderEmxDigital:   emx_digital.NewEmxDigitalBidder(cfg.Adapters[string(openrtb_ext.BidderEmxDigital)].Endpoint),
+		openrtb_ext.BidderEngageBDR:    engagebdr.NewEngageBDRBidder(client, cfg.Adapters[string(openrtb_ext.BidderEngageBDR)].Endpoint),
+		openrtb_ext.BidderEPlanning:    eplanning.NewEPlanningBidder(client, cfg.Adapters[string(openrtb_ext.BidderEPlanning)].Endpoint),
 		openrtb_ext.BidderFacebook: audienceNetwork.NewFacebookBidder(
 			client,
 			cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderFacebook))].PlatformID,
@@ -108,6 +112,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderMarsmedia:       marsmedia.NewMarsmediaBidder(cfg.Adapters[string(openrtb_ext.BidderMarsmedia)].Endpoint),
 		openrtb_ext.BidderMgid:            mgid.NewMgidBidder(cfg.Adapters[string(openrtb_ext.BidderMgid)].Endpoint),
 		openrtb_ext.BidderNanoInteractive: nanointeractive.NewNanoIneractiveBidder(cfg.Adapters[string(openrtb_ext.BidderNanoInteractive)].Endpoint),
+		openrtb_ext.BidderNinthDecimal:    ninthdecimal.NewNinthDecimalBidder(cfg.Adapters[string(openrtb_ext.BidderNinthDecimal)].Endpoint),
 		openrtb_ext.BidderOpenx:           openx.NewOpenxBidder(cfg.Adapters[string(openrtb_ext.BidderOpenx)].Endpoint),
 		openrtb_ext.BidderPubmatic:        pubmatic.NewPubmaticBidder(client, cfg.Adapters[string(openrtb_ext.BidderPubmatic)].Endpoint),
 		openrtb_ext.BidderPubnative:       pubnative.NewPubnativeBidder(cfg.Adapters[string(openrtb_ext.BidderPubnative)].Endpoint),
@@ -127,6 +132,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderSovrn:            sovrn.NewSovrnBidder(client, cfg.Adapters[string(openrtb_ext.BidderSovrn)].Endpoint),
 		openrtb_ext.BidderSynacormedia:     synacormedia.NewSynacorMediaBidder(cfg.Adapters[string(openrtb_ext.BidderSynacormedia)].Endpoint),
 		openrtb_ext.BidderTappx:            tappx.NewTappxBidder(client, cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderTappx))].Endpoint),
+		openrtb_ext.BidderTelaria:          telaria.NewTelariaBidder(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderTelaria))].Endpoint),
 		openrtb_ext.BidderTriplelift:       triplelift.NewTripleliftBidder(client, cfg.Adapters[string(openrtb_ext.BidderTriplelift)].Endpoint),
 		openrtb_ext.BidderTripleliftNative: triplelift_native.NewTripleliftNativeBidder(client, cfg.Adapters[string(openrtb_ext.BidderTripleliftNative)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderTripleliftNative)].ExtraAdapterInfo),
 		openrtb_ext.BidderUcfunnel:         ucfunnel.NewUcfunnelBidder(cfg.Adapters[string(openrtb_ext.BidderUcfunnel)].Endpoint),
@@ -136,6 +142,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderVisx:             visx.NewVisxBidder(cfg.Adapters[string(openrtb_ext.BidderVisx)].Endpoint),
 		openrtb_ext.BidderVrtcal:           vrtcal.NewVrtcalBidder(cfg.Adapters[string(openrtb_ext.BidderVrtcal)].Endpoint),
 		openrtb_ext.BidderYieldmo:          yieldmo.NewYieldmoBidder(cfg.Adapters[string(openrtb_ext.BidderYieldmo)].Endpoint),
+		openrtb_ext.BidderYieldone:         yieldone.NewYieldoneBidder(cfg.Adapters[string(openrtb_ext.BidderYieldone)].Endpoint),
 		openrtb_ext.BidderZeroClickFraud:   zeroclickfraud.NewZeroClickFraudBidder(cfg.Adapters[string(openrtb_ext.BidderZeroClickFraud)].Endpoint),
 	}
 
diff --git a/exchange/bidder.go b/exchange/bidder.go
index 8e95835f..7a53db5e 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -224,26 +224,43 @@ func addNativeTypes(bid *openrtb.Bid, request *openrtb.BidRequest) (*nativeRespo
 	}
 
 	for _, asset := range nativeMarkup.Assets {
-		setAssetTypes(asset, nativePayload)
+		if err := setAssetTypes(asset, nativePayload); err != nil {
+			errs = append(errs, err)
+		}
 	}
 
 	return nativeMarkup, errs
 }
 
-func setAssetTypes(asset nativeResponse.Asset, nativePayload nativeRequests.Request) {
+func setAssetTypes(asset nativeResponse.Asset, nativePayload nativeRequests.Request) error {
 	if asset.Img != nil {
-		tempAsset := getAssetByID(asset.ID, nativePayload.Assets)
-		if tempAsset.Img.Type != 0 {
-			asset.Img.Type = tempAsset.Img.Type
+		if tempAsset, err := getAssetByID(asset.ID, nativePayload.Assets); err == nil {
+			if tempAsset.Img != nil {
+				if tempAsset.Img.Type != 0 {
+					asset.Img.Type = tempAsset.Img.Type
+				}
+			} else {
+				return fmt.Errorf("Response has an Image asset with ID:%d present that doesn't exist in the request", asset.ID)
+			}
+		} else {
+			return err
 		}
 	}
 
 	if asset.Data != nil {
-		tempAsset := getAssetByID(asset.ID, nativePayload.Assets)
-		if tempAsset.Data.Type != 0 {
-			asset.Data.Type = tempAsset.Data.Type
+		if tempAsset, err := getAssetByID(asset.ID, nativePayload.Assets); err == nil {
+			if tempAsset.Data != nil {
+				if tempAsset.Data.Type != 0 {
+					asset.Data.Type = tempAsset.Data.Type
+				}
+			} else {
+				return fmt.Errorf("Response has a Data asset with ID:%d present that doesn't exist in the request", asset.ID)
+			}
+		} else {
+			return err
 		}
 	}
+	return nil
 }
 
 func getNativeImpByImpID(impID string, request *openrtb.BidRequest) (*openrtb.Native, error) {
@@ -255,13 +272,13 @@ func getNativeImpByImpID(impID string, request *openrtb.BidRequest) (*openrtb.Na
 	return nil, errors.New("Could not find native imp")
 }
 
-func getAssetByID(id int64, assets []nativeRequests.Asset) nativeRequests.Asset {
+func getAssetByID(id int64, assets []nativeRequests.Asset) (nativeRequests.Asset, error) {
 	for _, asset := range assets {
 		if id == asset.ID {
-			return asset
+			return asset, nil
 		}
 	}
-	return nativeRequests.Asset{}
+	return nativeRequests.Asset{}, fmt.Errorf("Unable to find asset with ID:%d in the request", id)
 }
 
 // makeExt transforms information about the HTTP call into the contract class for the PBS response.
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 3cab1880..48903dd9 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -63,6 +63,9 @@ type exchange struct {
 type seatResponseExtra struct {
 	ResponseTimeMillis int
 	Errors             []openrtb_ext.ExtBidderError
+	// 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
 }
 
 type bidResponseWrapper struct {
@@ -179,6 +182,12 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
 					errs = append(errs, errors.New("Unable to marshal response ext for debugging"))
 				}
 			}
+
+			if requestExt.Prebid.SupportDeals {
+				dealErrs := applyDealSupport(bidRequest, auc, bidCategory)
+				errs = append(errs, dealErrs...)
+			}
+
 			cacheErrs := auc.doCache(ctx, e.cache, targData, bidRequest, 60, &e.defaultTTLs, bidCategory, debugLog)
 			if len(cacheErrs) > 0 {
 				errs = append(errs, cacheErrs...)
@@ -186,10 +195,6 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
 			targData.setTargeting(auc, bidRequest.App != nil, bidCategory)
 		}
 
-		if requestExt.Prebid.SupportDeals {
-			dealErrs := applyDealSupport(bidRequest, auc)
-			errs = append(errs, dealErrs...)
-		}
 	}
 
 	// Build the response
@@ -210,7 +215,7 @@ type BidderDealTier struct {
 }
 
 // applyDealSupport updates targeting keys with deal prefixes if minimum deal tier exceeded
-func applyDealSupport(bidRequest *openrtb.BidRequest, auc *auction) []error {
+func applyDealSupport(bidRequest *openrtb.BidRequest, auc *auction, bidCategory map[string]string) []error {
 	errs := []error{}
 	impDealMap := getDealTiers(bidRequest)
 
@@ -221,7 +226,7 @@ func applyDealSupport(bidRequest *openrtb.BidRequest, auc *auction) []error {
 
 			if topBidPerBidder.dealPriority > 0 {
 				if validateAndNormalizeDealTier(impDeal[bidderString]) {
-					updateHbPbCatDur(topBidPerBidder, impDeal[bidderString].Info)
+					updateHbPbCatDur(topBidPerBidder, impDeal[bidderString].Info, bidCategory)
 				} else {
 					errs = append(errs, fmt.Errorf("dealTier configuration invalid for bidder '%s', imp ID '%s'", bidderString, impID))
 				}
@@ -258,16 +263,16 @@ func validateAndNormalizeDealTier(impDeal *DealTier) bool {
 	return len(impDeal.Info.Prefix) > 0 && impDeal.Info.MinDealTier > 0
 }
 
-func updateHbPbCatDur(bid *pbsOrtbBid, dealTierInfo *DealTierInfo) {
+func updateHbPbCatDur(bid *pbsOrtbBid, dealTierInfo *DealTierInfo, bidCategory map[string]string) {
 	if bid.dealPriority >= dealTierInfo.MinDealTier {
 		prefixTier := fmt.Sprintf("%s%d_", dealTierInfo.Prefix, bid.dealPriority)
 
-		if oldCatDur, ok := bid.bidTargets["hb_pb_cat_dur"]; ok {
+		if oldCatDur, ok := bidCategory[bid.bid.ID]; ok {
 			oldCatDurSplit := strings.SplitAfterN(oldCatDur, "_", 2)
 			oldCatDurSplit[0] = prefixTier
 
 			newCatDur := strings.Join(oldCatDurSplit, "")
-			bid.bidTargets["hb_pb_cat_dur"] = newCatDur
+			bidCategory[bid.bid.ID] = newCatDur
 		}
 	}
 }
@@ -322,6 +327,10 @@ func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext
 			// Structure to record extra tracking data generated during bidding
 			ae := new(seatResponseExtra)
 			ae.ResponseTimeMillis = int(elapsed / time.Millisecond)
+			if bids != nil {
+				ae.HttpCalls = bids.httpCalls
+			}
+
 			// Timing statistics
 			e.me.RecordAdapterTime(*bidlabels, time.Since(start))
 			serr := errsToBidderErrors(err)
@@ -344,7 +353,12 @@ func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext
 	// Wait for the bidders to do their thing
 	for i := 0; i < len(cleanRequests); i++ {
 		brw := <-chBids
-		adapterBids[brw.bidder] = brw.adapterBids
+
+		//if bidder returned no bids back - remove bidder from further processing
+		if brw.adapterBids != nil && len(brw.adapterBids.bids) != 0 {
+			adapterBids[brw.bidder] = brw.adapterBids
+		}
+		//but we need to add all bidders data to adapterExtra to have metrics and other metadata
 		adapterExtra[brw.bidder] = brw.adapterExtra
 
 		if !bidsFound && adapterBids[brw.bidder] != nil && len(adapterBids[brw.bidder].bids) > 0 {
@@ -637,20 +651,20 @@ func (e *exchange) makeExtBidResponse(adapterBids map[openrtb_ext.BidderName]*pb
 		}
 	}
 
-	for a, b := range adapterBids {
-		if b != nil && req.Test == 1 {
-			// Fill debug info
-			bidResponseExt.Debug.HttpCalls[a] = b.httpCalls
+	for bidderName, responseExtra := range adapterExtra {
+
+		if req.Test == 1 {
+			bidResponseExt.Debug.HttpCalls[bidderName] = responseExtra.HttpCalls
 		}
 		// Only make an entry for bidder errors if the bidder reported any.
-		if len(adapterExtra[a].Errors) > 0 {
-			bidResponseExt.Errors[a] = adapterExtra[a].Errors
+		if len(responseExtra.Errors) > 0 {
+			bidResponseExt.Errors[bidderName] = responseExtra.Errors
 		}
 		if len(errList) > 0 {
 			bidResponseExt.Errors[openrtb_ext.PrebidExtKey] = errsToBidderErrors(errList)
 		}
-		bidResponseExt.ResponseTimeMillis[a] = adapterExtra[a].ResponseTimeMillis
-		// Defering the filling of bidResponseExt.Usersync[a] until later
+		bidResponseExt.ResponseTimeMillis[bidderName] = responseExtra.ResponseTimeMillis
+		// Defering the filling of bidResponseExt.Usersync[bidderName] until later
 
 	}
 	return bidResponseExt
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
old mode 100644
new mode 100755
index ec974556..f8973469
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -26,6 +26,7 @@ const BidderNameGeneral = BidderName("general")
 const (
 	Bidder33Across         BidderName = "33across"
 	BidderAdform           BidderName = "adform"
+	BidderAdgeneration     BidderName = "adgeneration"
 	BidderAdkernel         BidderName = "adkernel"
 	BidderAdkernelAdn      BidderName = "adkernelAdn"
 	BidderAdpone           BidderName = "adpone"
@@ -58,6 +59,7 @@ const (
 	BidderMarsmedia        BidderName = "marsmedia"
 	BidderMgid             BidderName = "mgid"
 	BidderNanoInteractive  BidderName = "nanointeractive"
+	BidderNinthDecimal     BidderName = "ninthdecimal"
 	BidderOpenx            BidderName = "openx"
 	BidderPubmatic         BidderName = "pubmatic"
 	BidderPubnative        BidderName = "pubnative"
@@ -72,6 +74,7 @@ const (
 	BidderSovrn            BidderName = "sovrn"
 	BidderSynacormedia     BidderName = "synacormedia"
 	BidderTappx            BidderName = "tappx"
+	BidderTelaria          BidderName = "telaria"
 	BidderTriplelift       BidderName = "triplelift"
 	BidderTripleliftNative BidderName = "triplelift_native"
 	BidderUcfunnel         BidderName = "ucfunnel"
@@ -81,6 +84,7 @@ const (
 	BidderVisx             BidderName = "visx"
 	BidderVrtcal           BidderName = "vrtcal"
 	BidderYieldmo          BidderName = "yieldmo"
+	BidderYieldone         BidderName = "yieldone"
 	BidderZeroClickFraud   BidderName = "zeroclickfraud"
 )
 
@@ -89,6 +93,7 @@ const (
 var BidderMap = map[string]BidderName{
 	"33across":          Bidder33Across,
 	"adform":            BidderAdform,
+	"adgeneration":      BidderAdgeneration,
 	"adkernel":          BidderAdkernel,
 	"adkernelAdn":       BidderAdkernelAdn,
 	"admixer":           BidderAdmixer,
@@ -121,6 +126,7 @@ var BidderMap = map[string]BidderName{
 	"marsmedia":         BidderMarsmedia,
 	"mgid":              BidderMgid,
 	"nanointeractive":   BidderNanoInteractive,
+	"ninthdecimal":      BidderNinthDecimal,
 	"openx":             BidderOpenx,
 	"pubmatic":          BidderPubmatic,
 	"pubnative":         BidderPubnative,
@@ -135,6 +141,7 @@ var BidderMap = map[string]BidderName{
 	"sovrn":             BidderSovrn,
 	"synacormedia":      BidderSynacormedia,
 	"tappx":             BidderTappx,
+	"telaria":           BidderTelaria,
 	"triplelift":        BidderTriplelift,
 	"triplelift_native": BidderTripleliftNative,
 	"ucfunnel":          BidderUcfunnel,
@@ -144,6 +151,7 @@ var BidderMap = map[string]BidderName{
 	"visx":              BidderVisx,
 	"vrtcal":            BidderVrtcal,
 	"yieldmo":           BidderYieldmo,
+	"yieldone":          BidderYieldone,
 	"zeroclickfraud":    BidderZeroClickFraud,
 }
 
diff --git a/openrtb_ext/imp_adgeneration.go b/openrtb_ext/imp_adgeneration.go
new file mode 100644
index 00000000..97834f2c
--- /dev/null
+++ b/openrtb_ext/imp_adgeneration.go
@@ -0,0 +1,5 @@
+package openrtb_ext
+
+type ExtImpAdgeneration struct {
+	Id string `json:"id"`
+}
diff --git a/openrtb_ext/imp_ninthdecimal.go b/openrtb_ext/imp_ninthdecimal.go
new file mode 100755
index 00000000..8fb794db
--- /dev/null
+++ b/openrtb_ext/imp_ninthdecimal.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ExtImpNinthDecimal struct {
+	PublisherID string `json:"pubid"`
+	Placement   string `json:"placement,omitempty"`
+}
diff --git a/openrtb_ext/imp_telaria.go b/openrtb_ext/imp_telaria.go
new file mode 100644
index 00000000..8ea371a8
--- /dev/null
+++ b/openrtb_ext/imp_telaria.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ExtImpTelaria struct {
+	AdCode   string `json:"adCode,omitempty"`
+	SeatCode string `json:"seatCode"`
+}
diff --git a/openrtb_ext/imp_yieldone.go b/openrtb_ext/imp_yieldone.go
new file mode 100644
index 00000000..6eee563b
--- /dev/null
+++ b/openrtb_ext/imp_yieldone.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+// ExtImpYieldone defines the contract for bidrequest.imp[i].ext.yieldone
+type ExtImpYieldone struct {
+	PlacementId string `json:"placementId"`
+}
diff --git a/pbsmetrics/config/metrics.go b/pbsmetrics/config/metrics.go
index 81cfbfd0..e1cdaceb 100644
--- a/pbsmetrics/config/metrics.go
+++ b/pbsmetrics/config/metrics.go
@@ -181,6 +181,13 @@ func (me *MultiMetricsEngine) RecordPrebidCacheRequestTime(success bool, length
 	}
 }
 
+// RecordRequestQueueTime across all engines
+func (me *MultiMetricsEngine) RecordRequestQueueTime(success bool, requestType pbsmetrics.RequestType, length time.Duration) {
+	for _, thisME := range *me {
+		thisME.RecordRequestQueueTime(success, requestType, length)
+	}
+}
+
 // DummyMetricsEngine is a Noop metrics engine in case no metrics are configured. (may also be useful for tests)
 type DummyMetricsEngine struct{}
 
@@ -251,3 +258,7 @@ func (me *DummyMetricsEngine) RecordStoredImpCacheResult(cacheResult pbsmetrics.
 // RecordPrebidCacheRequestTime as a noop
 func (me *DummyMetricsEngine) RecordPrebidCacheRequestTime(success bool, length time.Duration) {
 }
+
+// RecordRequestQueueTime as a noop
+func (me *DummyMetricsEngine) RecordRequestQueueTime(success bool, requestType pbsmetrics.RequestType, length time.Duration) {
+}
diff --git a/pbsmetrics/go_metrics.go b/pbsmetrics/go_metrics.go
index 9b3dd65f..ff3d9681 100644
--- a/pbsmetrics/go_metrics.go
+++ b/pbsmetrics/go_metrics.go
@@ -24,6 +24,7 @@ type Metrics struct {
 	SafariRequestMeter             metrics.Meter
 	SafariNoCookieMeter            metrics.Meter
 	RequestTimer                   metrics.Timer
+	RequestsQueueTimer             map[RequestType]map[bool]metrics.Timer
 	PrebidCacheRequestTimerSuccess metrics.Timer
 	PrebidCacheRequestTimerError   metrics.Timer
 	StoredReqCacheMeter            map[CacheResult]metrics.Meter
@@ -111,6 +112,7 @@ func NewBlankMetrics(registry metrics.Registry, exchanges []openrtb_ext.BidderNa
 		SafariRequestMeter:             blankMeter,
 		SafariNoCookieMeter:            blankMeter,
 		RequestTimer:                   blankTimer,
+		RequestsQueueTimer:             make(map[RequestType]map[bool]metrics.Timer),
 		PrebidCacheRequestTimerSuccess: blankTimer,
 		PrebidCacheRequestTimerError:   blankTimer,
 		StoredReqCacheMeter:            make(map[CacheResult]metrics.Meter),
@@ -146,6 +148,11 @@ func NewBlankMetrics(registry metrics.Registry, exchanges []openrtb_ext.BidderNa
 		}
 	}
 
+	//to minimize memory usage, queuedTimeout metric is now supported for video endpoint only
+	//boolean value represents 2 general request statuses: accepted and rejected
+	newMetrics.RequestsQueueTimer["video"] = make(map[bool]metrics.Timer)
+	newMetrics.RequestsQueueTimer["video"][true] = blankTimer
+	newMetrics.RequestsQueueTimer["video"][false] = blankTimer
 	return newMetrics
 }
 
@@ -191,11 +198,15 @@ func NewMetrics(registry metrics.Registry, exchanges []openrtb_ext.BidderName, d
 			statusMap[stat] = metrics.GetOrRegisterMeter("requests."+string(stat)+"."+string(typ), registry)
 		}
 	}
+
 	for _, cacheRes := range CacheResults() {
 		newMetrics.StoredReqCacheMeter[cacheRes] = metrics.GetOrRegisterMeter(fmt.Sprintf("stored_request_cache_%s", string(cacheRes)), registry)
 		newMetrics.StoredImpCacheMeter[cacheRes] = metrics.GetOrRegisterMeter(fmt.Sprintf("stored_imp_cache_%s", string(cacheRes)), registry)
 	}
 
+	newMetrics.RequestsQueueTimer["video"][true] = metrics.GetOrRegisterTimer("queued_requests.video.accepted", registry)
+	newMetrics.RequestsQueueTimer["video"][false] = metrics.GetOrRegisterTimer("queued_requests.video.rejected", registry)
+
 	newMetrics.userSyncSet[unknownBidder] = metrics.GetOrRegisterMeter("usersync.unknown.sets", registry)
 	newMetrics.userSyncGDPRPrevent[unknownBidder] = metrics.GetOrRegisterMeter("usersync.unknown.gdpr_prevent", registry)
 	return newMetrics
@@ -526,6 +537,13 @@ func (me *Metrics) RecordPrebidCacheRequestTime(success bool, length time.Durati
 	}
 }
 
+func (me *Metrics) RecordRequestQueueTime(success bool, requestType RequestType, length time.Duration) {
+	if requestType == ReqTypeVideo { //remove this check when other request types are supported
+		me.RequestsQueueTimer[requestType][success].Update(length)
+	}
+
+}
+
 func doMark(bidder openrtb_ext.BidderName, meters map[openrtb_ext.BidderName]metrics.Meter) {
 	met, ok := meters[bidder]
 	if ok {
diff --git a/pbsmetrics/metrics.go b/pbsmetrics/metrics.go
index cc836011..611692c9 100644
--- a/pbsmetrics/metrics.go
+++ b/pbsmetrics/metrics.go
@@ -154,11 +154,12 @@ func CookieTypes() []CookieFlag {
 
 // Request/return status
 const (
-	RequestStatusOK          RequestStatus = "ok"
-	RequestStatusBadInput    RequestStatus = "badinput"
-	RequestStatusErr         RequestStatus = "err"
-	RequestStatusNetworkErr  RequestStatus = "networkerr"
-	RequestStatusBlacklisted RequestStatus = "blacklistedacctorapp"
+	RequestStatusOK           RequestStatus = "ok"
+	RequestStatusBadInput     RequestStatus = "badinput"
+	RequestStatusErr          RequestStatus = "err"
+	RequestStatusNetworkErr   RequestStatus = "networkerr"
+	RequestStatusBlacklisted  RequestStatus = "blacklistedacctorapp"
+	RequestStatusQueueTimeout RequestStatus = "queuetimeout"
 )
 
 func RequestStatuses() []RequestStatus {
@@ -168,6 +169,7 @@ func RequestStatuses() []RequestStatus {
 		RequestStatusErr,
 		RequestStatusNetworkErr,
 		RequestStatusBlacklisted,
+		RequestStatusQueueTimeout,
 	}
 }
 
@@ -272,4 +274,5 @@ type MetricsEngine interface {
 	RecordStoredReqCacheResult(cacheResult CacheResult, inc int)
 	RecordStoredImpCacheResult(cacheResult CacheResult, inc int)
 	RecordPrebidCacheRequestTime(success bool, length time.Duration)
+	RecordRequestQueueTime(success bool, requestType RequestType, length time.Duration)
 }
diff --git a/pbsmetrics/metrics_mock.go b/pbsmetrics/metrics_mock.go
index 6d57f9fc..1f5b84b1 100644
--- a/pbsmetrics/metrics_mock.go
+++ b/pbsmetrics/metrics_mock.go
@@ -96,3 +96,8 @@ func (me *MetricsEngineMock) RecordStoredImpCacheResult(cacheResult CacheResult,
 func (me *MetricsEngineMock) RecordPrebidCacheRequestTime(success bool, length time.Duration) {
 	me.Called(success, length)
 }
+
+// RecordRequestQueueTime mock
+func (me *MetricsEngineMock) RecordRequestQueueTime(success bool, requestType RequestType, length time.Duration) {
+	me.Called(success, requestType, length)
+}
diff --git a/pbsmetrics/prometheus/preload.go b/pbsmetrics/prometheus/preload.go
index 7654dd54..11e6bdc1 100644
--- a/pbsmetrics/prometheus/preload.go
+++ b/pbsmetrics/prometheus/preload.go
@@ -1,6 +1,7 @@
 package prometheusmetrics
 
 import (
+	"github.com/prebid/prebid-server/pbsmetrics"
 	"github.com/prometheus/client_golang/prometheus"
 )
 
@@ -91,6 +92,13 @@ func preloadLabelValues(m *Metrics) {
 		adapterLabel: adapterValues,
 		actionLabel:  actionValues,
 	})
+
+	//to minimize memory usage, queuedTimeout metric is now supported for video endpoint only
+	//boolean value represents 2 general request statuses: accepted and rejected
+	preloadLabelValuesForHistogram(m.requestsQueueTimer, map[string][]string{
+		requestTypeLabel:   {string(pbsmetrics.ReqTypeVideo)},
+		requestStatusLabel: {requestSuccessLabel, requestRejectLabel},
+	})
 }
 
 func preloadLabelValuesForCounter(counter *prometheus.CounterVec, labelsWithValues map[string][]string) {
diff --git a/pbsmetrics/prometheus/prometheus.go b/pbsmetrics/prometheus/prometheus.go
index e2b646d5..d66defea 100644
--- a/pbsmetrics/prometheus/prometheus.go
+++ b/pbsmetrics/prometheus/prometheus.go
@@ -24,6 +24,7 @@ type Metrics struct {
 	prebidCacheWriteTimer        *prometheus.HistogramVec
 	requests                     *prometheus.CounterVec
 	requestsTimer                *prometheus.HistogramVec
+	requestsQueueTimer           *prometheus.HistogramVec
 	requestsWithoutCookie        *prometheus.CounterVec
 	storedImpressionsCacheResult *prometheus.CounterVec
 	storedRequestCacheResult     *prometheus.CounterVec
@@ -73,11 +74,17 @@ const (
 	markupDeliveryNurl = "nurl"
 )
 
+const (
+	requestSuccessLabel = "requestAcceptedLabel"
+	requestRejectLabel  = "requestRejectedLabel"
+)
+
 // NewMetrics initializes a new Prometheus metrics instance with preloaded label values.
 func NewMetrics(cfg config.PrometheusMetrics) *Metrics {
 	requestTimeBuckets := []float64{0.05, 0.1, 0.15, 0.20, 0.25, 0.3, 0.4, 0.5, 0.75, 1}
 	cacheWriteTimeBuckets := []float64{0.001, 0.002, 0.005, 0.01, 0.025, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 1}
 	priceBuckets := []float64{250, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000}
+	queuedRequestTimeBuckets := []float64{0, 1, 5, 30, 60, 120, 180, 240, 300}
 
 	metrics := Metrics{}
 	metrics.Registry = prometheus.NewRegistry()
@@ -187,6 +194,12 @@ func NewMetrics(cfg config.PrometheusMetrics) *Metrics {
 		"Count of total requests to Prebid Server labeled by account.",
 		[]string{accountLabel})
 
+	metrics.requestsQueueTimer = newHistogram(cfg, metrics.Registry,
+		"request_queue_time",
+		"Seconds request was waiting in queue",
+		[]string{requestTypeLabel, requestStatusLabel},
+		queuedRequestTimeBuckets)
+
 	preloadLabelValues(&metrics)
 
 	return &metrics
@@ -374,3 +387,14 @@ func (m *Metrics) RecordPrebidCacheRequestTime(success bool, length time.Duratio
 		successLabel: strconv.FormatBool(success),
 	}).Observe(length.Seconds())
 }
+
+func (m *Metrics) RecordRequestQueueTime(success bool, requestType pbsmetrics.RequestType, length time.Duration) {
+	successLabelFormatted := requestRejectLabel
+	if success {
+		successLabelFormatted = requestSuccessLabel
+	}
+	m.requestsQueueTimer.With(prometheus.Labels{
+		requestTypeLabel:   string(requestType),
+		requestStatusLabel: successLabelFormatted,
+	}).Observe(length.Seconds())
+}
diff --git a/router/aspects/request_timeout_handler.go b/router/aspects/request_timeout_handler.go
index ae11f8c5..23d6cef9 100644
--- a/router/aspects/request_timeout_handler.go
+++ b/router/aspects/request_timeout_handler.go
@@ -3,11 +3,13 @@ package aspects
 import (
 	"github.com/julienschmidt/httprouter"
 	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/pbsmetrics"
 	"net/http"
 	"strconv"
+	"time"
 )
 
-func QueuedRequestTimeout(f httprouter.Handle, reqTimeoutHeaders config.RequestTimeoutHeaders) httprouter.Handle {
+func QueuedRequestTimeout(f httprouter.Handle, reqTimeoutHeaders config.RequestTimeoutHeaders, metricsEngine pbsmetrics.MetricsEngine, requestType pbsmetrics.RequestType) httprouter.Handle {
 
 	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
 
@@ -30,13 +32,17 @@ func QueuedRequestTimeout(f httprouter.Handle, reqTimeoutHeaders config.RequestT
 			return
 		}
 
+		reqTimeDuration := time.Duration(reqTimeFloat * float64(time.Second))
+
 		//Return HTTP 408 if requests stays too long in queue
 		if reqTimeFloat >= reqTimeoutFloat {
 			w.WriteHeader(http.StatusRequestTimeout)
 			w.Write([]byte("Queued request processing time exceeded maximum"))
+			metricsEngine.RecordRequestQueueTime(false, requestType, reqTimeDuration)
 			return
 		}
 
+		metricsEngine.RecordRequestQueueTime(true, requestType, reqTimeDuration)
 		f(w, r, params)
 	}
 
diff --git a/router/router.go b/router/router.go
index 8ac463b8..68627f93 100644
--- a/router/router.go
+++ b/router/router.go
@@ -6,6 +6,7 @@ import (
 	"database/sql"
 	"encoding/json"
 	"fmt"
+	"github.com/prebid/prebid-server/pbsmetrics"
 	"io/ioutil"
 	"net/http"
 	"path/filepath"
@@ -258,7 +259,7 @@ func New(cfg *config.Configuration, rateConvertor *currencies.RateConverter) (r
 
 	requestTimeoutHeaders := config.RequestTimeoutHeaders{}
 	if cfg.RequestTimeoutHeaders != requestTimeoutHeaders {
-		videoEndpoint = aspects.QueuedRequestTimeout(videoEndpoint, cfg.RequestTimeoutHeaders)
+		videoEndpoint = aspects.QueuedRequestTimeout(videoEndpoint, cfg.RequestTimeoutHeaders, r.MetricsEngine, pbsmetrics.ReqTypeVideo)
 	}
 
 	r.POST("/auction", endpoints.Auction(cfg, syncers, gdprPerms, r.MetricsEngine, dataCache, exchanges))
diff --git a/static/adapter/appnexus/opts.json b/static/adapter/appnexus/opts.json
index bd6f8af3..3ea84973 100644
--- a/static/adapter/appnexus/opts.json
+++ b/static/adapter/appnexus/opts.json
@@ -20,8 +20,11 @@
     "19": "IAB18-4",
     "20": "IAB1-5",
     "21": "IAB1-6",
+    "22": "IAB19-28",
     "23": "IAB19-13",
     "24": "IAB22-2",
+    "25": "IAB3-9",
+    "26": "IAB17-26",
     "27": "IAB19-6",
     "28": "IAB1-7",
     "29": "IAB9-5",
@@ -31,7 +34,6 @@
     "33": "IAB16-5",
     "34": "IAB19-34",
     "37": "IAB11-4",
-    "38": "IAB23",
     "39": "IAB9-30",
     "41": "IAB7-44",
     "51": "IAB17-12",
diff --git a/static/bidder-info/33across.yaml b/static/bidder-info/33across.yaml
index f0a44470..84ba6d68 100644
--- a/static/bidder-info/33across.yaml
+++ b/static/bidder-info/33across.yaml
@@ -1,9 +1,9 @@
 maintainer:
-  email: "dev@33across.com"
+  email: "headerbidding@33across.com"
 capabilities:
   app:
     mediaTypes:
     - banner
   site:
     mediaTypes:
-    - banner
\ No newline at end of file
+    - banner
diff --git a/static/bidder-info/adgeneration.yaml b/static/bidder-info/adgeneration.yaml
new file mode 100644
index 00000000..55f65314
--- /dev/null
+++ b/static/bidder-info/adgeneration.yaml
@@ -0,0 +1,10 @@
+maintainer:
+  email: "ssp-ope@supership.jp"
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+  site:
+    mediaTypes:
+      - banner
+
diff --git a/static/bidder-info/adoppler.yaml b/static/bidder-info/adoppler.yaml
index 7fa79eda..1b101039 100644
--- a/static/bidder-info/adoppler.yaml
+++ b/static/bidder-info/adoppler.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: info@adoppler.com
+  email: pbs@adoppler.com
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/advangelists.yaml b/static/bidder-info/advangelists.yaml
index e1bc6c0a..aed9900d 100644
--- a/static/bidder-info/advangelists.yaml
+++ b/static/bidder-info/advangelists.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "lokesh@advangelists.com"
+  email: "prebid@advangelists.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/appnexus.yaml b/static/bidder-info/appnexus.yaml
index 585c59b9..f1e7ca23 100644
--- a/static/bidder-info/appnexus.yaml
+++ b/static/bidder-info/appnexus.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "info@prebid.org"
+  email: "prebid-server@xandr.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/audienceNetwork.yaml b/static/bidder-info/audienceNetwork.yaml
index 34700f2f..56230bf3 100644
--- a/static/bidder-info/audienceNetwork.yaml
+++ b/static/bidder-info/audienceNetwork.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "info@prebid.org"
+  email: "none"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/brightroll.yaml b/static/bidder-info/brightroll.yaml
index 14d9a45f..f913be6d 100644
--- a/static/bidder-info/brightroll.yaml
+++ b/static/bidder-info/brightroll.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "smithaa@oath.com"
+  email: "dsp-supply-prebid@verizonmedia.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/conversant.yaml b/static/bidder-info/conversant.yaml
index ce67700e..017f0e0c 100644
--- a/static/bidder-info/conversant.yaml
+++ b/static/bidder-info/conversant.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "mediapsr@conversantmedia.com"
+  email: "CNVR_PublisherIntegration@conversantmedia.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/datablocks.yaml b/static/bidder-info/datablocks.yaml
index 9bf7e780..43f00a63 100644
--- a/static/bidder-info/datablocks.yaml
+++ b/static/bidder-info/datablocks.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "henry@datablocks.net"
+  email: "prebid@datablocks.net"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/engagebdr.yaml b/static/bidder-info/engagebdr.yaml
index d2f74762..57c359e4 100644
--- a/static/bidder-info/engagebdr.yaml
+++ b/static/bidder-info/engagebdr.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "admin@engagebdr.com"
+  email: "tech@engagebdr.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/gamoshi.yaml b/static/bidder-info/gamoshi.yaml
index 71120ed0..c3ed3ff1 100644
--- a/static/bidder-info/gamoshi.yaml
+++ b/static/bidder-info/gamoshi.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "moses@gamoshi.com"
+  email: "dev@gamoshi.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/gumgum.yaml b/static/bidder-info/gumgum.yaml
index b8a3981c..0feca7cd 100644
--- a/static/bidder-info/gumgum.yaml
+++ b/static/bidder-info/gumgum.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "pubtech@gumgum.com"
+  email: "prebid@gumgum.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/ix.yaml b/static/bidder-info/ix.yaml
index ff29ec03..326989ae 100644
--- a/static/bidder-info/ix.yaml
+++ b/static/bidder-info/ix.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "info@prebid.org"
+  email: "pdu-supply-prebid@indexexchange.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/ninthdecimal.yaml b/static/bidder-info/ninthdecimal.yaml
new file mode 100755
index 00000000..eda7d222
--- /dev/null
+++ b/static/bidder-info/ninthdecimal.yaml
@@ -0,0 +1,13 @@
+maintainer:
+  email: "abudig@ninthdecimal.com"
+capabilities:
+  site:
+    mediaTypes:
+    - banner
+    - video
+    
+  app:
+    mediaTypes:
+    - banner
+    - video
+   
diff --git a/static/bidder-info/openx.yaml b/static/bidder-info/openx.yaml
index ce2b67db..e3062b54 100644
--- a/static/bidder-info/openx.yaml
+++ b/static/bidder-info/openx.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "team-openx@openx.com"
+  email: "prebid@openx.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/pulsepoint.yaml b/static/bidder-info/pulsepoint.yaml
index b9fd3242..716e4530 100644
--- a/static/bidder-info/pulsepoint.yaml
+++ b/static/bidder-info/pulsepoint.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "info@prebid.org"
+  email: "ExchangeTeam@pulsepoint.com"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-info/rtbhouse.yaml b/static/bidder-info/rtbhouse.yaml
index 4b899eb3..f15af6ca 100644
--- a/static/bidder-info/rtbhouse.yaml
+++ b/static/bidder-info/rtbhouse.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "inventory.devel@rtbhouse.com"
+  email: "prebid@rtbhouse.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/sonobi.yaml b/static/bidder-info/sonobi.yaml
index f49fa281..6d39319a 100644
--- a/static/bidder-info/sonobi.yaml
+++ b/static/bidder-info/sonobi.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "apex@sonobi.com"
+  email: "apex.prebid@sonobi.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/telaria.yaml b/static/bidder-info/telaria.yaml
new file mode 100644
index 00000000..43e8707a
--- /dev/null
+++ b/static/bidder-info/telaria.yaml
@@ -0,0 +1,9 @@
+maintainer:
+  email: "github@telaria.com"
+capabilities:
+  app:
+    mediaTypes:
+      - video
+  site:
+    mediaTypes:
+      - video
diff --git a/static/bidder-info/verizonmedia.yaml b/static/bidder-info/verizonmedia.yaml
index da5725ee..024cafad 100644
--- a/static/bidder-info/verizonmedia.yaml
+++ b/static/bidder-info/verizonmedia.yaml
@@ -1,6 +1,6 @@
 maintainer:
-  email: "hb-fe-tech@verizonmedia.com"
+  email: "dsp-supply-prebid@verizonmedia.com"
 capabilities:
   site:
     mediaTypes:
-      - banner
\ No newline at end of file
+      - banner
diff --git a/static/bidder-info/visx.yaml b/static/bidder-info/visx.yaml
index f404a013..b6a16e4c 100644
--- a/static/bidder-info/visx.yaml
+++ b/static/bidder-info/visx.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "service@yoc.com"
+  email: "supply.partners@yoc.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/yieldmo.yaml b/static/bidder-info/yieldmo.yaml
index 7d6c0af6..514f1745 100644
--- a/static/bidder-info/yieldmo.yaml
+++ b/static/bidder-info/yieldmo.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "progsupport@yieldmo.com"
+  email: "prebid@yieldmo.com"
 capabilities:
   site:
     mediaTypes:
diff --git a/static/bidder-info/yieldone.yaml b/static/bidder-info/yieldone.yaml
new file mode 100644
index 00000000..74aef46d
--- /dev/null
+++ b/static/bidder-info/yieldone.yaml
@@ -0,0 +1,11 @@
+maintainer:
+  email: "y1dev@platform-one.co.jp"
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+  app:
+    mediaTypes:
+      - banner
+      - video
diff --git a/static/bidder-info/zeroclickfraud.yaml b/static/bidder-info/zeroclickfraud.yaml
index 9bf7e780..527c0065 100644
--- a/static/bidder-info/zeroclickfraud.yaml
+++ b/static/bidder-info/zeroclickfraud.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "henry@datablocks.net"
+  email: "support@datablocks.net"
 capabilities:
   app:
     mediaTypes:
diff --git a/static/bidder-params/adgeneration.json b/static/bidder-params/adgeneration.json
new file mode 100644
index 00000000..a4f761c3
--- /dev/null
+++ b/static/bidder-params/adgeneration.json
@@ -0,0 +1,15 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "AdGeneration Adapter Params",
+    "description": "A schema which validates params accepted by the AdGeneration adapter",
+  
+    "type": "object",
+    "properties": {
+        "id": {
+          "type": "string",
+          "description": "Ad ID registered by AdGeneration."
+        }
+    },
+    "required": ["id"]
+  }
+  
\ No newline at end of file
diff --git a/static/bidder-params/ninthdecimal.json b/static/bidder-params/ninthdecimal.json
new file mode 100755
index 00000000..f230361d
--- /dev/null
+++ b/static/bidder-params/ninthdecimal.json
@@ -0,0 +1,18 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "NinthDecimal Adapter Params",
+  "description": "A schema which validates params accepted by the NinthDecimal adapter",
+  "type": "object",
+  "properties": {
+    "pubid": {
+      "type": "string",
+      "description": "An id used to identify NinthDecimal publisher.",
+      "minLength": 8
+    },
+    "placement": {
+      "type": "string",
+      "description": "A placement created on adserver."
+    }
+  },
+  "required": ["pubid"]
+}
diff --git a/static/bidder-params/telaria.json b/static/bidder-params/telaria.json
new file mode 100644
index 00000000..b4121967
--- /dev/null
+++ b/static/bidder-params/telaria.json
@@ -0,0 +1,22 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Telaria Adapter Params",
+  "description": "A schema which validates params accepted by the Telaria adapter",
+
+  "type": "object",
+  "properties": {
+    "adCode": {
+      "type": "string",
+      "description": "The Ad Unit Code."
+    },
+    "seatCode": {
+      "type": "string",
+      "description": "Your Seat Code."
+    },
+    "originalPublisherid": {
+      "type": "string",
+      "description": "publisher ID from the original request"
+    }
+  },
+  "required": ["seatCode"]
+}
diff --git a/static/bidder-params/yieldone.json b/static/bidder-params/yieldone.json
new file mode 100644
index 00000000..15d7acec
--- /dev/null
+++ b/static/bidder-params/yieldone.json
@@ -0,0 +1,15 @@
+
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "Yieldone Adapter Params",
+    "description": "A schema which validates params accepted by the Yieldone adapter",
+  
+    "type": "object",
+    "properties": {
+      "placementId": {
+        "type": "string",
+        "description": "Internal Yieldone Placement ID"
+      }
+    },
+    "required": ["placementId"]
+  }
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
old mode 100644
new mode 100755
index be0392f2..3c0931f4
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -35,6 +35,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/marsmedia"
 	"github.com/prebid/prebid-server/adapters/mgid"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
+	"github.com/prebid/prebid-server/adapters/ninthdecimal"
 	"github.com/prebid/prebid-server/adapters/openx"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
 	"github.com/prebid/prebid-server/adapters/pulsepoint"
@@ -47,6 +48,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/sonobi"
 	"github.com/prebid/prebid-server/adapters/sovrn"
 	"github.com/prebid/prebid-server/adapters/synacormedia"
+	"github.com/prebid/prebid-server/adapters/telaria"
 	"github.com/prebid/prebid-server/adapters/triplelift"
 	"github.com/prebid/prebid-server/adapters/triplelift_native"
 	"github.com/prebid/prebid-server/adapters/ucfunnel"
@@ -56,6 +58,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/visx"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
 	"github.com/prebid/prebid-server/adapters/yieldmo"
+	"github.com/prebid/prebid-server/adapters/yieldone"
 	"github.com/prebid/prebid-server/adapters/zeroclickfraud"
 	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/openrtb_ext"
@@ -98,6 +101,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMarsmedia, marsmedia.NewMarsmediaSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMgid, mgid.NewMgidSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderNanoInteractive, nanointeractive.NewNanoInteractiveSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderNinthDecimal, ninthdecimal.NewNinthDecimalSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderOpenx, openx.NewOpenxSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderPubmatic, pubmatic.NewPubmaticSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderPulsepoint, pulsepoint.NewPulsepointSyncer)
@@ -110,6 +114,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderSovrn, sovrn.NewSovrnSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderSmartRTB, smartrtb.NewSmartRTBSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderSynacormedia, synacormedia.NewSynacorMediaSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderTelaria, telaria.NewTelariaSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderTriplelift, triplelift.NewTripleliftSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderTripleliftNative, triplelift_native.NewTripleliftSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderUcfunnel, ucfunnel.NewUcfunnelSyncer)
@@ -119,6 +124,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderVisx, visx.NewVisxSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderVrtcal, vrtcal.NewVrtcalSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderYieldmo, yieldmo.NewYieldmoSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderYieldone, yieldone.NewYieldoneSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderZeroClickFraud, zeroclickfraud.NewZeroClickFraudSyncer)
 
 	return syncers


Test patch:
diff --git a/adapters/adgeneration/adgeneration_test.go b/adapters/adgeneration/adgeneration_test.go
new file mode 100644
index 00000000..e76995fc
--- /dev/null
+++ b/adapters/adgeneration/adgeneration_test.go
@@ -0,0 +1,176 @@
+package adgeneration
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "adgenerationtest", NewAdgenerationAdapter("https://d.socdm.com/adsv/v1"))
+}
+
+func TestgetRequestUri(t *testing.T) {
+	bidder := NewAdgenerationAdapter("https://d.socdm.com/adsv/v1")
+	// Test items
+	failedRequest := &openrtb.BidRequest{
+		ID: "test-failed-bid-request",
+		Imp: []openrtb.Imp{
+			{ID: "extImpBidder-failed-test", Banner: &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}}}, Ext: json.RawMessage(`{{ "id": "58278" }}`)},
+			{ID: "extImpBidder-failed-test", Banner: &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}}}, Ext: json.RawMessage(`{"_bidder": { "id": "58278" }}`)},
+			{ID: "extImpAdgeneration-failed-test", Banner: &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}}}, Ext: json.RawMessage(`{"bidder": { "_id": "58278" }}`)},
+		},
+		Device: &openrtb.Device{UA: "testUA", IP: "testIP"},
+		Site:   &openrtb.Site{Page: "https://supership.com"},
+		User:   &openrtb.User{BuyerUID: "buyerID"},
+	}
+	successRequest := &openrtb.BidRequest{
+		ID: "test-success-bid-request",
+		Imp: []openrtb.Imp{
+			{ID: "bidRequest-success-test", Banner: &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}}}, Ext: json.RawMessage(`{"bidder": { "id": "58278" }}`)},
+		},
+		Device: &openrtb.Device{UA: "testUA", IP: "testIP"},
+		Site:   &openrtb.Site{Page: "https://supership.com"},
+		User:   &openrtb.User{BuyerUID: "buyerID"},
+	}
+
+	numRequests := len(failedRequest.Imp)
+	for index := 0; index < numRequests; index++ {
+		httpRequests, err := bidder.getRequestUri(failedRequest, index)
+		if err == nil {
+			t.Errorf("getRequestUri: %v did not throw an error", failedRequest.Imp[index])
+		}
+		if httpRequests != "" {
+			t.Errorf("getRequestUri: %v did return Request: %s", failedRequest.Imp[index], httpRequests)
+		}
+	}
+	numRequests = len(successRequest.Imp)
+	for index := 0; index < numRequests; index++ {
+		// RequestUri Test.
+		httpRequests, err := bidder.getRequestUri(successRequest, index)
+		if err != nil {
+			t.Errorf("getRequestUri: %v did throw an error: %v", successRequest.Imp[index], err)
+		}
+		if httpRequests == "adapterver="+bidder.version+"&currency=JPY&hb=true&id=58278&posall=SSPLOC&sdkname=prebidserver&sdktype=0&size=300%C3%97250&t=json3&tp=http%3A%2F%2Fexample.com%2Ftest.html" {
+			t.Errorf("getRequestUri: %v did return Request: %s", successRequest.Imp[index], httpRequests)
+		}
+		// getRawQuery Test.
+		adgExt, err := unmarshalExtImpAdgeneration(&successRequest.Imp[index])
+		if err != nil {
+			t.Errorf("unmarshalExtImpAdgeneration: %v did throw an error: %v", successRequest.Imp[index], err)
+		}
+		rawQuery := bidder.getRawQuery(adgExt.Id, successRequest, &successRequest.Imp[index])
+		expectQueries := map[string]string{
+			"posall":     "SSPLOC",
+			"id":         adgExt.Id,
+			"sdktype":    "0",
+			"hb":         "true",
+			"currency":   bidder.getCurrency(successRequest),
+			"sdkname":    "prebidserver",
+			"adapterver": bidder.version,
+			"size":       getSizes(&successRequest.Imp[index]),
+			"tp":         successRequest.Site.Name,
+		}
+		for key, expectedValue := range expectQueries {
+			actualValue := rawQuery.Get(key)
+			if actualValue == "" {
+				if !(key == "size" || key == "tp") {
+					t.Errorf("getRawQuery: key %s is required value.", key)
+				}
+			}
+			if actualValue != expectedValue {
+				t.Errorf("getRawQuery: %s value does not match expected %s, actual %s", key, expectedValue, actualValue)
+			}
+		}
+	}
+}
+
+func TestGetSizes(t *testing.T) {
+	// Test items
+	var request *openrtb.Imp
+	var size string
+	multiFormatBanner := &openrtb.Banner{Format: []openrtb.Format{{W: 300, H: 250}, {W: 320, H: 50}}}
+	noFormatBanner := &openrtb.Banner{Format: []openrtb.Format{}}
+	nativeFormat := &openrtb.Native{}
+
+	request = &openrtb.Imp{Banner: multiFormatBanner}
+	size = getSizes(request)
+	if size != "300×250,320×50" {
+		t.Errorf("%v does not match size.", multiFormatBanner)
+	}
+	request = &openrtb.Imp{Banner: noFormatBanner}
+	size = getSizes(request)
+	if size != "" {
+		t.Errorf("%v does not match size.", noFormatBanner)
+	}
+	request = &openrtb.Imp{Native: nativeFormat}
+	size = getSizes(request)
+	if size != "" {
+		t.Errorf("%v does not match size.", nativeFormat)
+	}
+}
+
+func TestGetCurrency(t *testing.T) {
+	bidder := NewAdgenerationAdapter("https://d.socdm.com/adsv/v1")
+	// Test items
+	var request *openrtb.BidRequest
+	var currency string
+	innerDefaultCur := []string{"USD", "JPY"}
+	usdCur := []string{"USD", "EUR"}
+
+	request = &openrtb.BidRequest{Cur: innerDefaultCur}
+	currency = bidder.getCurrency(request)
+	if currency != "JPY" {
+		t.Errorf("%v does not match currency.", innerDefaultCur)
+	}
+	request = &openrtb.BidRequest{Cur: usdCur}
+	currency = bidder.getCurrency(request)
+	if currency != "USD" {
+		t.Errorf("%v does not match currency.", usdCur)
+	}
+}
+
+func TestCreateAd(t *testing.T) {
+	// Test items
+	adgBannerImpId := "test-banner-imp"
+	adgBannerResponse := adgServerResponse{
+		Ad:         "<!DOCTYPE html>\n<head>\n<meta charset=\"UTF-8\">\n<script src=\"test.com\"></script>\n<body>\n<div id=\"medibasspContainer\">\n<iframe src=\"https://dummy-iframe.com></iframe>\n</div>\n</body>\n",
+		Beacon:     "<img src=\"https://dummy-beacon.com\">",
+		Beaconurl:  "https://dummy-beacon.com",
+		Cpm:        50,
+		Creativeid: "DummyDsp_SdkTeam_supership.jp",
+		H:          300,
+		W:          250,
+		Ttl:        10,
+		LandingUrl: "",
+		Scheduleid: "111111",
+	}
+	matchBannerTag := "<div id=\"medibasspContainer\">\n<iframe src=\"https://dummy-iframe.com></iframe>\n</div>\n<img src=\"https://dummy-beacon.com\">"
+
+	adgVastImpId := "test-vast-imp"
+	adgVastResponse := adgServerResponse{
+		Ad:         "<!DOCTYPE html>\n<head>\n<meta charset=\"UTF-8\">\n<script src=\"test.com\"></script>\n<body>\n<div id=\"medibasspContainer\">\n<iframe src=\"https://dummy-iframe.com></iframe>\n</div>\n</body>\n",
+		Beacon:     "<img src=\"https://dummy-beacon.com\">",
+		Beaconurl:  "https://dummy-beacon.com",
+		Cpm:        50,
+		Creativeid: "DummyDsp_SdkTeam_supership.jp",
+		H:          300,
+		W:          250,
+		Ttl:        10,
+		LandingUrl: "",
+		Vastxml:    "<?xml version=\"1.0\"><VAST version=\"3.0\"</VAST>",
+		Scheduleid: "111111",
+	}
+	matchVastTag := "<div id=\"apvad-test-vast-imp\"></div><script type=\"text/javascript\" id=\"apv\" src=\"https://cdn.apvdr.com/js/VideoAd.min.js\"></script><script type=\"text/javascript\"> (function(){ new APV.VideoAd({s:\"test-vast-imp\"}).load('<?xml version=\"1.0\"><VAST version=\"3.0\"</VAST>'); })(); </script><img src=\"https://dummy-beacon.com\">"
+
+	bannerAd := createAd(&adgBannerResponse, adgBannerImpId)
+	if bannerAd != matchBannerTag {
+		t.Errorf("%v does not match createAd.", adgBannerResponse)
+	}
+	vastAd := createAd(&adgVastResponse, adgVastImpId)
+	if vastAd != matchVastTag {
+		t.Errorf("%v does not match createAd.", adgVastResponse)
+	}
+}
diff --git a/adapters/adgeneration/adgenerationtest/exemplary/single-banner.json b/adapters/adgeneration/adgenerationtest/exemplary/single-banner.json
new file mode 100644
index 00000000..d23a510b
--- /dev/null
+++ b/adapters/adgeneration/adgenerationtest/exemplary/single-banner.json
@@ -0,0 +1,151 @@
+{
+    "mockBidRequest":{
+        "id": "some-request-id",
+        "site": {
+            "page": "http://example.com/test.html"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "id": "58278"
+                    }
+                }
+            }
+        ],
+        "tmax": 500
+    },
+    "httpCalls": [
+        {
+            "internalRequest": {
+                "id": "some-request-id",
+                "site": {
+                    "page": "http://example.com/test.html"
+                },
+                "imp": [
+                    {
+                        "id": "some-impression-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "id": "58278"
+                            }
+                        }
+                    }
+                ],
+                "tmax": 500
+            },
+            "expectedRequest":{
+                "uri": "https://d.socdm.com/adsv/v1?adapterver=1.0.0&currency=JPY&hb=true&id=58278&posall=SSPLOC&sdkname=prebidserver&sdktype=0&size=300%C3%97250&t=json3&tp=http%3A%2F%2Fexample.com%2Ftest.html",
+                "headers": {
+                    "Accept": [
+                        "application/json"
+                    ],
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                }
+            },
+            "mockResponse":{
+                "status": 200,
+                "body": {
+                    "ad": "<!DOCTYPE html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <script src=\"https:\/\/i.socdm.com\/sdk\/js\/adg-script-base.js\" type=\"text\/javascript\"><\/script>\n    <script type=\"text\/javascript\">\n      adsettings = {\n        locationid  : 58278,\n        rotation    : 0,\n        displaytype : 1,\n        sdktype     : \"0\",\n        scheduleid  : 512601\n      };\n    <\/script>\n    <style>\n      body {\n        margin:0;\n        padding:0;\n      }\n    <\/style>\n  <\/head>\n  <body>\n    <div id=\"medibasspContainer\">\n      <iframe src=\"https:\/\/s3-ap-northeast-1.amazonaws.com\/sdk-temp\/adg-sample-ad\/300x250.html?prc=-Cuepak&rd=https%3A%2F%2Ftg.socdm.com%2Frd%2Fv1%2Fz%2FhKFj2gDXY2hzbT0xOTgsZmJkZGMyNWEvNTgyNzgvU1NQTE9DLzUxMjYwMS83MjExNS43Njg1NS41MTI2MDEvMTA5MzkyNi82NDkxOS81ODI3ODpTU1BMT0M6Ki9jdD0xNTg1MjEyMDg1Nzg5O3NyPWh0dHBzO2RzcGlkPTMwMTtwcj16RGFfYVY0O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTA5LjQzMDAwMDAwMDAwMDAxO2NyeTJkPTAuMDA5MTM4MjYxOTAyNTg2MTI3MztpZHg9MDulc2VxaWTaACQ0NzFhM2JlNS1lYTQzLWRhZjAtYjhjZi1mNjJkNTA1N2Y5ZWOnc2VxdGltZa0xNTg1MjEyMDg1Nzg5pHh1aWS4WE52SVNNQ281bUlBQU1hN2dOUUFBQUFB%2Fp%2Fctsv%3Dm-ad226%3Bseqid%3D471a3be5-ea43-daf0-b8cf-f62d5057f9ec%3B%2Fg%2FU%3A%3Furl%3D\" style=\"border: 0px;\" width=\"300\" height=\"250\" frameborder=\"0\" scrolling=\"no\"><\/iframe>\n    <\/div>\n  <\/body>\n",
+                    "beacon": "<img src=\"https://tg.socdm.com/bc/v3?b=beaconID&amp;xuid=XUID&amp;ctsv=CTSV&amp;seqid=SeqID&amp;seqtime=SeqTime&amp;seqctx=SeqCtx&amp;t=.gif\" width=\"1\" height=\"1\" style=\"display:none;border:none;padding:0;margin:0;width:1px;height:1px\"/>",
+                    "beaconurl": "https://tg.socdm.com/bc/v3?b=beaconID&t=.gif",
+                    "cpm": 46.6,
+                    "creativeid": "Dummy_supership.jp",
+                    "displaytype": "1",
+                    "h": 250,
+                    "ids": {
+                        "anid": "",
+                        "diid": "",
+                        "idfa": "",
+                        "soc": "Soc"
+                    },
+                    "location_params": null,
+                    "locationid": "58278",
+                    "results": [
+                        {
+                            "ad": "<!DOCTYPE html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <script src=\"https:\/\/i.socdm.com\/sdk\/js\/adg-script-base.js\" type=\"text\/javascript\"><\/script>\n    <script type=\"text\/javascript\">\n      adsettings = {\n        locationid  : 58278,\n        rotation    : 0,\n        displaytype : 1,\n        sdktype     : \"0\",\n        scheduleid  : 512601\n      };\n    <\/script>\n    <style>\n      body {\n        margin:0;\n        padding:0;\n      }\n    <\/style>\n  <\/head>\n  <body>\n    <div id=\"medibasspContainer\">\n      <iframe src=\"https:\/\/s3-ap-northeast-1.amazonaws.com\/sdk-temp\/adg-sample-ad\/300x250.html?prc=-Cuepak&rd=https%3A%2F%2Ftg.socdm.com%2Frd%2Fv1%2Fz%2FhKFj2gDXY2hzbT0xOTgsZmJkZGMyNWEvNTgyNzgvU1NQTE9DLzUxMjYwMS83MjExNS43Njg1NS41MTI2MDEvMTA5MzkyNi82NDkxOS81ODI3ODpTU1BMT0M6Ki9jdD0xNTg1MjEyMDg1Nzg5O3NyPWh0dHBzO2RzcGlkPTMwMTtwcj16RGFfYVY0O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTA5LjQzMDAwMDAwMDAwMDAxO2NyeTJkPTAuMDA5MTM4MjYxOTAyNTg2MTI3MztpZHg9MDulc2VxaWTaACQ0NzFhM2JlNS1lYTQzLWRhZjAtYjhjZi1mNjJkNTA1N2Y5ZWOnc2VxdGltZa0xNTg1MjEyMDg1Nzg5pHh1aWS4WE52SVNNQ281bUlBQU1hN2dOUUFBQUFB%2Fp%2Fctsv%3Dm-ad226%3Bseqid%3D471a3be5-ea43-daf0-b8cf-f62d5057f9ec%3B%2Fg%2FU%3A%3Furl%3D\" style=\"border: 0px;\" width=\"300\" height=\"250\" frameborder=\"0\" scrolling=\"no\"><\/iframe>\n    <\/div>\n  <\/body>\n",
+                            "beacon": "<img src=\"https://tg.socdm.com/bc/v3?b=beaconID&amp;xuid=XUID&amp;ctsv=CTSV&amp;seqid=SeqID&amp;seqtime=SeqTime&amp;seqctx=SeqCtx&amp;t=.gif\" width=\"1\" height=\"1\" style=\"display:none;border:none;padding:0;margin:0;width:1px;height:1px\"/>",
+                            "beaconurl": "https://tg.socdm.com/bc/v3?b=beaconID&t=.gif",
+                            "cpm": 46.6,
+                            "creativeid": "Dummy_supership.jp",
+                            "h": 250,
+                            "landing_url": "",
+                            "scheduleid": "512601",
+                            "trackers": {
+                                "imp": [
+                                    "https://tg.socdm.com/bc/v3?b=beaconID&t=.gif"
+                                ],
+                                "viewable_imp": [
+                                    "https://tg.socdm.com/aux/inview?creative_id=1093926&ctsv=CTSC&extra_field=ExtraField&family_id=512601&id=58278&loglocation_id=64919&lookupname=58278%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=72115.76855.512601&seqid=SeqID&seqtime=SeqTime&xuid=XUID"
+                                ],
+                                "viewable_measured": [
+                                    "https://tg.socdm.com/aux/measured?creative_id=1093926&ctsv=CTSC&extra_field=ExtraField&family_id=512601&id=58278&loglocation_id=64919&lookupname=58278%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=72115.76855.512601&seqid=SeqID&seqtime=SeqTime&xuid=XUID"
+                                ]
+                            },
+                            "ttl": 10,
+                            "w": 300,
+                            "weight": 1
+                        }
+                    ],
+                    "dealid": "test-deal-id",
+                    "rotation": "0",
+                    "scheduleid": "512601",
+                    "sdktype": "0",
+                    "trackers": {
+                        "imp": [
+                            "https://tg.socdm.com/bc/v3?b=beaconID&t=.gif"
+                        ],
+                        "viewable_imp": [
+                            "https://tg.socdm.com/aux/inview?creative_id=1093926&ctsv=CTSC&extra_field=ExtraField&family_id=512601&id=58278&loglocation_id=64919&lookupname=58278%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=72115.76855.512601&seqid=SeqID&seqtime=SeqTime&xuid=XUID"
+                        ],
+                        "viewable_measured": [
+                            "https://tg.socdm.com/aux/measured?creative_id=1093926&ctsv=CTSC&extra_field=ExtraField&family_id=512601&id=58278&loglocation_id=64919&lookupname=58278%3ASSPLOC%3A*&pos=SSPLOC&schedule_id=72115.76855.512601&seqid=SeqID&seqtime=SeqTime&xuid=XUID"
+                        ]
+                    },
+                    "ttl": 10,
+                    "w": 300
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+          "currency": "JPY",
+          "bids": [
+            {
+              "bid": {
+                "id": "58278",
+                "impid": "some-impression-id",
+                "price": 46.6,
+                "adm": "<div id=\"medibasspContainer\">\n      <iframe src=\"https:\/\/s3-ap-northeast-1.amazonaws.com\/sdk-temp\/adg-sample-ad\/300x250.html?prc=-Cuepak&rd=https%3A%2F%2Ftg.socdm.com%2Frd%2Fv1%2Fz%2FhKFj2gDXY2hzbT0xOTgsZmJkZGMyNWEvNTgyNzgvU1NQTE9DLzUxMjYwMS83MjExNS43Njg1NS41MTI2MDEvMTA5MzkyNi82NDkxOS81ODI3ODpTU1BMT0M6Ki9jdD0xNTg1MjEyMDg1Nzg5O3NyPWh0dHBzO2RzcGlkPTMwMTtwcj16RGFfYVY0O3ByYj15UTtwcm89eVE7cHJvYz1KUFk7Y3JkMnk9MTA5LjQzMDAwMDAwMDAwMDAxO2NyeTJkPTAuMDA5MTM4MjYxOTAyNTg2MTI3MztpZHg9MDulc2VxaWTaACQ0NzFhM2JlNS1lYTQzLWRhZjAtYjhjZi1mNjJkNTA1N2Y5ZWOnc2VxdGltZa0xNTg1MjEyMDg1Nzg5pHh1aWS4WE52SVNNQ281bUlBQU1hN2dOUUFBQUFB%2Fp%2Fctsv%3Dm-ad226%3Bseqid%3D471a3be5-ea43-daf0-b8cf-f62d5057f9ec%3B%2Fg%2FU%3A%3Furl%3D\" style=\"border: 0px;\" width=\"300\" height=\"250\" frameborder=\"0\" scrolling=\"no\"><\/iframe>\n    <\/div>\n  <img src=\"https://tg.socdm.com/bc/v3?b=beaconID&amp;xuid=XUID&amp;ctsv=CTSV&amp;seqid=SeqID&amp;seqtime=SeqTime&amp;seqctx=SeqCtx&amp;t=.gif\" width=\"1\" height=\"1\" style=\"display:none;border:none;padding:0;margin:0;width:1px;height:1px\"/>",
+                "crid": "Dummy_supership.jp",
+                "w": 300,
+                "h": 250,
+                "dealid": "test-deal-id"
+              },
+              "type": "banner"
+            }
+          ]
+        }
+      ]
+}
+
diff --git a/adapters/adgeneration/adgenerationtest/params/race/banner.json b/adapters/adgeneration/adgenerationtest/params/race/banner.json
new file mode 100644
index 00000000..0aa81b38
--- /dev/null
+++ b/adapters/adgeneration/adgenerationtest/params/race/banner.json
@@ -0,0 +1,3 @@
+{
+    "id": "58278"
+}
diff --git a/adapters/adgeneration/adgenerationtest/supplemental/204-bid-response.json b/adapters/adgeneration/adgenerationtest/supplemental/204-bid-response.json
new file mode 100644
index 00000000..cf8635bb
--- /dev/null
+++ b/adapters/adgeneration/adgenerationtest/supplemental/204-bid-response.json
@@ -0,0 +1,72 @@
+{
+    "mockBidRequest":{
+        "id": "some-request-id",
+        "site": {
+            "page": "http://example.com/test.html"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "id": "58278"
+                    }
+                }
+            }
+        ],
+        "tmax": 500
+    },
+    "httpCalls": [
+        {
+            "internalRequest": {
+                "id": "some-request-id",
+                "site": {
+                    "page": "http://example.com/test.html"
+                },
+                "imp": [
+                    {
+                        "id": "some-impression-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "id": "58278"
+                            }
+                        }
+                    }
+                ],
+                "tmax": 500
+            },
+            "expectedRequest":{
+                "uri": "https://d.socdm.com/adsv/v1?adapterver=1.0.0&currency=JPY&hb=true&id=58278&posall=SSPLOC&sdkname=prebidserver&sdktype=0&size=300%C3%97250&t=json3&tp=http%3A%2F%2Fexample.com%2Ftest.html",
+                "headers": {
+                    "Accept": [
+                        "application/json"
+                    ],
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 204,
+                "body": {}
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/adgeneration/adgenerationtest/supplemental/400-bid-response.json b/adapters/adgeneration/adgenerationtest/supplemental/400-bid-response.json
new file mode 100644
index 00000000..f5dc7fe0
--- /dev/null
+++ b/adapters/adgeneration/adgenerationtest/supplemental/400-bid-response.json
@@ -0,0 +1,77 @@
+{
+    "mockBidRequest":{
+        "id": "some-request-id",
+        "site": {
+            "page": "http://example.com/test.html"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "id": "58278"
+                    }
+                }
+            }
+        ],
+        "tmax": 500
+    },
+    "httpCalls": [
+        {
+            "internalRequest": {
+                "id": "some-request-id",
+                "site": {
+                    "page": "http://example.com/test.html"
+                },
+                "imp": [
+                    {
+                        "id": "some-impression-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "id": "58278"
+                            }
+                        }
+                    }
+                ],
+                "tmax": 500
+            },
+            "expectedRequest":{
+                "uri": "https://d.socdm.com/adsv/v1?adapterver=1.0.0&currency=JPY&hb=true&id=58278&posall=SSPLOC&sdkname=prebidserver&sdktype=0&size=300%C3%97250&t=json3&tp=http%3A%2F%2Fexample.com%2Ftest.html",
+                "headers": {
+                    "Accept": [
+                        "application/json"
+                    ],
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 400,
+                "body": {}
+            }
+        }
+    ],
+    "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/adgeneration/adgenerationtest/supplemental/invalid-adg-param.json b/adapters/adgeneration/adgenerationtest/supplemental/invalid-adg-param.json
new file mode 100644
index 00000000..4353ceaf
--- /dev/null
+++ b/adapters/adgeneration/adgenerationtest/supplemental/invalid-adg-param.json
@@ -0,0 +1,31 @@
+{
+    "mockBidRequest":{
+        "id": "some-request-id",
+        "site": {
+            "page": "http://example.com/test.html"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "_id": "12345"
+                    }
+                }
+            }
+        ],
+        "tmax": 500
+    },
+    "expectedMakeRequestsErrors": [{
+        "value": "No Location ID in ExtImpAdgeneration.",
+        "comparison": "literal"
+    }]
+}
diff --git a/adapters/adgeneration/adgenerationtest/supplemental/no-bid-response.json b/adapters/adgeneration/adgenerationtest/supplemental/no-bid-response.json
new file mode 100644
index 00000000..399f85a5
--- /dev/null
+++ b/adapters/adgeneration/adgenerationtest/supplemental/no-bid-response.json
@@ -0,0 +1,89 @@
+{
+    "mockBidRequest":{
+        "id": "some-request-id",
+        "site": {
+            "page": "http://example.com/test.html"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "id": "58278"
+                    }
+                }
+            }
+        ],
+        "tmax": 500
+    },
+    "httpCalls": [
+        {
+            "internalRequest": {
+                "id": "some-request-id",
+                "site": {
+                    "page": "http://example.com/test.html"
+                },
+                "imp": [
+                    {
+                        "id": "some-impression-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "id": "58278"
+                            }
+                        }
+                    }
+                ],
+                "tmax": 500
+            },
+            "expectedRequest":{
+                "uri": "https://d.socdm.com/adsv/v1?adapterver=1.0.0&currency=JPY&hb=true&id=58278&posall=SSPLOC&sdkname=prebidserver&sdktype=0&size=300%C3%97250&t=json3&tp=http%3A%2F%2Fexample.com%2Ftest.html",
+                "headers": {
+                    "Accept": [
+                        "application/json"
+                    ],
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ]
+                }
+            },
+            "mockResponse":{
+                "status": 200,
+                "body": {
+                    "ad": "<!-- st=noad : id=58278 : pos=SSPLOC -->\n",
+                    "beacon": "<img src=\"https://tg.socdm.com/bc/v3?b=beaconID&amp;xuid=XUID&amp;ctsv=CTSV&amp;seqid=SeqID&amp;seqtime=SeqTime&amp;seqctx=SeqCtx&amp;t=.gif\" width=\"1\" height=\"1\" style=\"display:none;border:none;padding:0;margin:0;width:1px;height:1px\"/>",
+                    "beaconurl": "https://tg.socdm.com/bc/v3?b=beaconID&t=.gif",
+                    "displaytype": "1",
+                    "ids": {
+                        "anid": "",
+                        "diid": "",
+                        "idfa": "",
+                        "soc": "XNvISMCo5mIAAMa7gNQAAAAA"
+                    },
+                    "location_params": null,
+                    "locationid": "58278",
+                    "results": [],
+                    "rotation": "0",
+                    "sdktype": "0"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
+
diff --git a/adapters/adgeneration/params_test.go b/adapters/adgeneration/params_test.go
new file mode 100644
index 00000000..062d122a
--- /dev/null
+++ b/adapters/adgeneration/params_test.go
@@ -0,0 +1,47 @@
+package adgeneration
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderAdgeneration, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected adgeneration params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderAdgeneration, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"id":"12345"}`,
+	`{"id":"123456"}`,
+	`{"id":""}`,
+	`{"id":"12345","other_params":"hoge"}`,
+}
+
+var invalidParams = []string{
+	`{}`,
+	`null`,
+	`12345`,
+	`{"id":123456}`,
+}
diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json
index 632629b5..f5f92515 100644
--- a/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json
+++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json
@@ -51,7 +51,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "imp": [
                         {
                             "id": "test-imp-id",
@@ -84,7 +84,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -92,7 +92,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "seatbid": [
                         {
                             "bid": [
diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json
index 630e26d3..bad228d5 100644
--- a/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json
+++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json
@@ -52,7 +52,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "imp": [
                         {
                             "id": "test-imp-id",
@@ -86,7 +86,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -94,7 +94,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "seatbid": [
                         {
                             "bid": [
diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json
index 288c7c14..9090d80d 100644
--- a/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json
+++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json
@@ -45,7 +45,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "imp": [
                         {
                             "id": "test-imp-id",
@@ -78,7 +78,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -86,7 +86,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "seatbid": [
                         {
                             "bid": [
diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json
index 15563c2a..22c62f8b 100644
--- a/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json
+++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json
@@ -50,7 +50,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "imp": [
                         {
                             "id": "test-imp-id",
@@ -88,7 +88,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -96,7 +96,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "seatbid": [
                         {
                             "bid": [
diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json
index 52b76555..3edd6569 100644
--- a/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json
+++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json
@@ -53,7 +53,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "imp": [
                         {
                             "id": "test-imp-id",
@@ -86,7 +86,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -94,7 +94,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "seatbid": [
                         {
                             "bid": [
diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json
index 0fe836af..16e8aede 100644
--- a/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json
+++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json
@@ -70,7 +70,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-1",
                     "imp": [
                         {
                             "id": "test-imp-1",
@@ -103,7 +103,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "dfecd103a45daeb2a01728afb8ce78f6738f6007ecfebe1ca616b196e22b43e9",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -111,7 +111,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-1",
                     "seatbid": [
                         {
                             "bid": [
@@ -147,7 +147,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-2",
                     "imp": [
                         {
                             "id": "test-imp-2",
@@ -180,7 +180,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "a5fead11a4db86d0f62f57c3d8001640227120c8ef236549f0db010c1dbab399",
                         "platformid": "test-platform-id"
                     }
                 }
@@ -188,7 +188,7 @@
             "mockResponse": {
                 "status": 200,
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-2",
                     "seatbid": [
                         {
                             "bid": [
diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json
index 042c86bd..bb192aad 100644
--- a/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json
+++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json
@@ -45,7 +45,7 @@
                     ]
                 },
                 "body": {
-                    "id": "test-req-id",
+                    "id": "test-imp-id",
                     "imp": [
                         {
                             "id": "test-imp-id",
@@ -78,7 +78,7 @@
                     },
                     "tmax": 500,
                     "ext": {
-                        "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+                        "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
                         "platformid": "test-platform-id"
                     }
                 }
diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json
index b99834ab..4c561c55 100644
--- a/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json
+++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json
@@ -39,7 +39,7 @@
       "expectedRequest": {
         "uri": "https://an.facebook.com/placementbid.ortb",
         "body": {
-          "id": "test-req-id",
+          "id": "test-imp-id",
           "imp": [
             {
               "id": "test-imp-id",
@@ -72,7 +72,7 @@
           },
           "tmax": 500,
           "ext": {
-              "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e",
+              "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174",
               "platformid": "test-platform-id"
           }
         }
@@ -80,7 +80,7 @@
       "mockResponse": {
         "status": 200,
         "body": {
-          "id": "test-req-id",
+          "id": "test-imp-id",
           "seatbid": [
             {
               "bid": [
diff --git a/adapters/audienceNetwork/facebook_test.go b/adapters/audienceNetwork/facebook_test.go
index 1edaabd4..784a540e 100644
--- a/adapters/audienceNetwork/facebook_test.go
+++ b/adapters/audienceNetwork/facebook_test.go
@@ -43,9 +43,9 @@ func TestJsonSamples(t *testing.T) {
 	adapterstest.RunJSONBidderTest(t, "audienceNetworktest", NewFacebookBidder(nil, "test-platform-id", "test-app-secret"))
 }
 
-func TestMakeTimeoutNotice(t *testing.T) {
+func TestMakeTimeoutNoticeApp(t *testing.T) {
 	req := adapters.RequestData{
-		Body: []byte(`{"imp":[{"id":"1234"}]}}`),
+		Body: []byte(`{"id":"1234","imp":[{"id":"1234"}],"app":{"publisher":{"id":"5678"}}}`),
 	}
 	fba := NewFacebookBidder(nil, "test-platform-id", "test-app-secret")
 
@@ -56,9 +56,25 @@ func TestMakeTimeoutNotice(t *testing.T) {
 
 	toReq, err := tb.MakeTimeoutNotification(&req)
 	assert.Nil(t, err, "Facebook MakeTimeoutNotification() return an error %v", err)
-	expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=test-platform-id&auction=1234&ortb_loss_code=2"
+	expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=5678&auction=1234&ortb_loss_code=2"
 	assert.Equal(t, expectedUri, toReq.Uri, "Facebook timeout notification not returning the expected URI.")
+}
 
+func TestMakeTimeoutNoticeSite(t *testing.T) {
+	req := adapters.RequestData{
+		Body: []byte(`{"id":"1234","imp":[{"id":"1234"}],"site":{"publisher":{"id":"5678"}}}`),
+	}
+	fba := NewFacebookBidder(nil, "test-platform-id", "test-app-secret")
+
+	tb, ok := fba.(adapters.TimeoutBidder)
+	if !ok {
+		t.Error("Facebook adapter is not a TimeoutAdapter")
+	}
+
+	toReq, err := tb.MakeTimeoutNotification(&req)
+	assert.Nil(t, err, "Facebook MakeTimeoutNotification() return an error %v", err)
+	expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=5678&auction=1234&ortb_loss_code=2"
+	assert.Equal(t, expectedUri, toReq.Uri, "Facebook timeout notification not returning the expected URI.")
 }
 
 func TestMakeTimeoutNoticeBadRequest(t *testing.T) {
diff --git a/adapters/beachfront/beachfront_test.go b/adapters/beachfront/beachfront_test.go
index 4e82deaf..c220cebf 100644
--- a/adapters/beachfront/beachfront_test.go
+++ b/adapters/beachfront/beachfront_test.go
@@ -7,5 +7,5 @@ import (
 )
 
 func TestJsonSamples(t *testing.T) {
-	adapterstest.RunJSONBidderTest(t, "beachfronttest", new(BeachfrontAdapter))
+	adapterstest.RunJSONBidderTest(t, "beachfronttest", NewBeachfrontBidder("https://display.bfmio.com/prebid_display", "{\"video_endpoint\":\"https://reachms.bfmio.com/bid.json?exchange_id\"}"))
 }
diff --git a/adapters/beachfront/beachfronttest/exemplary/minimal-banner.json b/adapters/beachfront/beachfronttest/exemplary/minimal-banner.json
index ffcea194..51ce4e92 100644
--- a/adapters/beachfront/beachfronttest/exemplary/minimal-banner.json
+++ b/adapters/beachfront/beachfronttest/exemplary/minimal-banner.json
@@ -56,7 +56,7 @@
           "dnt": 0,
           "ua": "",
           "adapterName": "BF_PREBID_S2S",
-          "adapterVersion": "0.8.0",
+          "adapterVersion": "0.9.0",
           "user": {
           }
         }
diff --git a/adapters/beachfront/beachfronttest/exemplary/simple-mix.json b/adapters/beachfront/beachfronttest/exemplary/simple-mix.json
index 6d8e483e..eb5d9b07 100644
--- a/adapters/beachfront/beachfronttest/exemplary/simple-mix.json
+++ b/adapters/beachfront/beachfronttest/exemplary/simple-mix.json
@@ -85,7 +85,7 @@
             "buyeruid": "some-buyer"
           },
           "adapterName": "BF_PREBID_S2S",
-          "adapterVersion": "0.8.0",
+          "adapterVersion": "0.9.0",
           "ip": "192.168.255.255",
           "requestId": "61b87329-8790-47b7-90dd-c53ae7ce1723"
         }
diff --git a/adapters/beachfront/beachfronttest/supplemental/minimal-banner-empty_array-200.json b/adapters/beachfront/beachfronttest/supplemental/minimal-banner-empty_array-200.json
index f189b2c8..7bdbc73c 100644
--- a/adapters/beachfront/beachfronttest/supplemental/minimal-banner-empty_array-200.json
+++ b/adapters/beachfront/beachfronttest/supplemental/minimal-banner-empty_array-200.json
@@ -56,7 +56,7 @@
           "dnt": 0,
           "ua": "",
           "adapterName": "BF_PREBID_S2S",
-          "adapterVersion": "0.8.0",
+          "adapterVersion": "0.9.0",
           "user": {
           }
         }
diff --git a/adapters/beachfront/beachfronttest/supplemental/minimal-site-banner.json b/adapters/beachfront/beachfronttest/supplemental/minimal-site-banner.json
index b610c96f..27b24357 100644
--- a/adapters/beachfront/beachfronttest/supplemental/minimal-site-banner.json
+++ b/adapters/beachfront/beachfronttest/supplemental/minimal-site-banner.json
@@ -56,7 +56,7 @@
             "dnt": 0,
             "ua": "",
             "adapterName": "BF_PREBID_S2S",
-            "adapterVersion": "0.8.0",
+            "adapterVersion": "0.9.0",
             "user": {
             }
           }
diff --git a/adapters/beachfront/beachfronttest/supplemental/mobile-banner.json b/adapters/beachfront/beachfronttest/supplemental/mobile-banner.json
index d47393b7..ea38d7ad 100644
--- a/adapters/beachfront/beachfronttest/supplemental/mobile-banner.json
+++ b/adapters/beachfront/beachfronttest/supplemental/mobile-banner.json
@@ -87,7 +87,7 @@
 
           },
           "adapterName":"BF_PREBID_S2S",
-          "adapterVersion":"0.8.0",
+          "adapterVersion":"0.9.0",
           "ip":"192.168.255.255",
           "requestId":"763e3312-19d5-4b07-a61d-890147e863a1"
         }
diff --git a/adapters/beachfront/beachfronttest/supplemental/multi-banner.json b/adapters/beachfront/beachfronttest/supplemental/multi-banner.json
index c4120787..46699511 100644
--- a/adapters/beachfront/beachfronttest/supplemental/multi-banner.json
+++ b/adapters/beachfront/beachfronttest/supplemental/multi-banner.json
@@ -96,7 +96,7 @@
           "dnt": 1,
           "ua": "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16",
           "adapterName": "BF_PREBID_S2S",
-          "adapterVersion": "0.8.0",
+          "adapterVersion": "0.9.0",
           "user": {
             "buyeruid": "some-buyer",
             "id": "some-user"
diff --git a/adapters/ninthdecimal/ninthdecimal_test.go b/adapters/ninthdecimal/ninthdecimal_test.go
new file mode 100755
index 00000000..206455a6
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimal_test.go
@@ -0,0 +1,10 @@
+package ninthdecimal
+
+import (
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"testing"
+)
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "ninthdecimaltest", NewNinthDecimalBidder("http://rtb.ninthdecimal.com/xp/get?pubid={{.PublisherID}}"))
+}
diff --git a/adapters/ninthdecimal/ninthdecimaltest/exemplary/banner.json b/adapters/ninthdecimal/ninthdecimaltest/exemplary/banner.json
new file mode 100644
index 00000000..d2184fa0
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/exemplary/banner.json
@@ -0,0 +1,95 @@
+{
+  "mockBidRequest": {
+    "id": "testid",
+    "imp": [
+      {
+        "id": "testimpid",
+        "banner": {
+          "format": [
+            {
+              "w": 320,
+              "h": 250
+            },
+            {
+              "w": 320,
+              "h": 300
+            }
+          ],
+          "w": 320,
+          "h": 250
+        },
+        "ext": {
+          "bidder": {
+            "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+            "placement": "dummyplacement"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://rtb.ninthdecimal.com/xp/get?pubid=19f1b372c7548ec1fe734d2c9f8dc688",
+        "body":{
+          "id": "testid",
+          "imp": [{
+            "id": "testimpid",
+            "tagid": "dummyplacement",
+            "banner": {
+              "format": [{
+                "w": 320,
+                "h": 250
+              }, {
+                "w": 320,
+                "h": 300
+              }],
+              "w": 320,
+              "h": 250
+            }
+            
+          }]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "crid": "24080",
+                   "adid": "2068416",
+                  "price": 0.01,
+                  "id": "testid",
+                  "impid": "testimpid",
+                  "cid": "8048"
+                }
+              ]
+            }
+          ]
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "crid": "24080",
+           "adid": "2068416",
+            "price": 0.01,
+            "id": "testid",
+            "impid": "testimpid",
+            "cid": "8048"
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/ninthdecimal/ninthdecimaltest/exemplary/video.json b/adapters/ninthdecimal/ninthdecimaltest/exemplary/video.json
new file mode 100644
index 00000000..4ad093e0
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/exemplary/video.json
@@ -0,0 +1,83 @@
+{
+  "mockBidRequest": {
+    "id": "testid",
+    "imp": [
+      {
+        "id": "testimpid",
+        "video": {
+            "mimes": [
+              "video/mp4"
+            ],
+            "w": 640,
+            "h": 480
+          },
+        "ext": {
+          "bidder": {
+            "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+            "placement": "dummyplacement"
+          }
+        }
+      }
+    ]
+  },
+  
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://rtb.ninthdecimal.com/xp/get?pubid=19f1b372c7548ec1fe734d2c9f8dc688",
+        "body":{
+          "id": "testid",
+          "imp": [{
+            "id": "testimpid",
+            "tagid": "dummyplacement",
+            "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "w": 640,
+                "h": 480
+              }
+          }]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "crid": "24080",
+                   "adid": "2068416",
+                  "price": 0.01,
+                  "id": "testid",
+                  "impid": "testimpid",
+                  "cid": "8048"
+                }
+              ]
+            }
+          ]
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "crid": "24080",
+           "adid": "2068416",
+            "price": 0.01,
+            "id": "testid",
+            "impid": "testimpid",
+            "cid": "8048"
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/params/race/banner.json b/adapters/ninthdecimal/ninthdecimaltest/params/race/banner.json
new file mode 100644
index 00000000..2eed8f2e
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/params/race/banner.json
@@ -0,0 +1,4 @@
+{
+  "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+  "placement": "dummyplacement"
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/params/race/video.json b/adapters/ninthdecimal/ninthdecimaltest/params/race/video.json
new file mode 100644
index 00000000..2eed8f2e
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/params/race/video.json
@@ -0,0 +1,4 @@
+{
+  "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+  "placement": "dummyplacement"
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/checkImp.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/checkImp.json
new file mode 100644
index 00000000..ca48812b
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/checkImp.json
@@ -0,0 +1,14 @@
+{
+    "mockBidRequest": {
+      "id": "testid",
+      "site": {
+        "id": "test",
+        "domain": "test.com"
+      }
+    },
+    "expectedMakeRequestsErrors": [
+      {
+          "value": "No impression in the bid request",
+          "comparison": "literal"
+      }]
+  }
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/compat.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/compat.json
new file mode 100644
index 00000000..ff33b59c
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/compat.json
@@ -0,0 +1,80 @@
+{
+  "mockBidRequest": {
+    "id": "testid",
+    "imp": [
+      {
+        "id": "testimpid",
+        "banner": {
+          "format": [{
+            "w": 320,
+            "h": 250
+          }]
+        },
+        "ext": {
+          "bidder": {
+            "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+            "placement": "dummyplacement"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://rtb.ninthdecimal.com/xp/get?pubid=19f1b372c7548ec1fe734d2c9f8dc688",
+        "body":{
+          "id": "testid",
+          "imp": [{
+            "banner": {
+              "h": 250,
+              "w": 320
+              },
+              "id": "testimpid",
+              "tagid": "dummyplacement"
+            
+          }]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "crid": "24080",
+                   "adid": "2068416",
+                  "price": 0.01,
+                  "id": "testid",
+                  "impid": "testimpid",
+                  "cid": "8048"
+                }
+              ]
+            }
+          ]
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "crid": "24080",
+           "adid": "2068416",
+            "price": 0.01,
+            "id": "testid",
+            "impid": "testimpid",
+            "cid": "8048"
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/ext.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/ext.json
new file mode 100644
index 00000000..3cfb878b
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/ext.json
@@ -0,0 +1,33 @@
+{
+  "mockBidRequest": {
+    "id": "testid",
+    "imp": [
+      {
+        "id": "testimpid",
+        "banner": {
+          "format": [
+            {
+              "w": 320,
+              "h": 250
+            },
+            {
+              "w": 320,
+              "h": 300
+            }
+          ],
+          "w": 320,
+          "h": 250
+        },
+        "ext": {
+            "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+            "placement": "dummyplacement"
+        }
+      }
+    ]
+  },
+"expectedMakeRequestsErrors": [
+    {
+        "value": "unexpected end of JSON input",
+        "comparison": "literal"
+    }]
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/missingpub.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/missingpub.json
new file mode 100644
index 00000000..b088917a
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/missingpub.json
@@ -0,0 +1,35 @@
+{
+    "mockBidRequest": {
+      "id": "testid",
+      "imp": [
+        {
+          "id": "testimpid",
+          "banner": {
+            "format": [
+              {
+                "w": 320,
+                "h": 250
+              },
+              {
+                "w": 320,
+                "h": 300
+              }
+            ],
+            "w": 320,
+            "h": 250
+          },
+          "ext": {
+            "bidder": {
+              "pubid": "",
+              "placement": "dummyplacement"
+            }
+          }
+        }
+      ]
+    },
+    "expectedMakeRequestsErrors": [
+      {
+          "value": "No pubid value provided",
+          "comparison": "literal"
+      }]
+  }
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/responseCode.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/responseCode.json
new file mode 100644
index 00000000..a68db2b8
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/responseCode.json
@@ -0,0 +1,78 @@
+{
+  "mockBidRequest": {
+      "id": "testid",
+      "site": {
+          "id": "test"
+      },
+      "imp": [
+          {
+              "id": "testimpid",
+              "banner": {
+                  "format": [
+                      {
+                          "w": 320,
+                          "h": 250
+                      },
+                      {
+                          "w": 320,
+                          "h": 300
+                      }
+                  ],
+                  "w": 320,
+                  "h": 250
+              },
+              "ext": {
+                  "bidder": {
+                      "pubid": "yu",
+                      "placement": "dummyplacement"
+                  }
+              }
+          }
+      ]
+  },
+  "httpCalls": [
+      {
+          "expectedRequest": {
+              "uri": "http://rtb.ninthdecimal.com/xp/get?pubid=yu",
+              "body": {
+                  "id": "testid",
+                  "imp": [
+                      {
+                          "banner": {
+                              "format": [
+                                  {
+                                      "h": 250,
+                                      "w": 320
+                                  },
+                                  {
+                                      "h": 300,
+                                      "w": 320
+                                  }
+                              ],
+                              "h": 250,
+                              "w": 320
+                          },
+                          "id": "testimpid",
+                          "tagid": "dummyplacement"
+                      }
+                  ],
+                  "site": {
+                      "id": "test"
+                  }
+              }
+          },
+          "mockResponse": {
+            "body": {
+                "seatbid": []
+            }
+        }
+    }
+
+  ],
+  "expectedMakeBidsErrors": [
+    {
+        "value": "Unexpected http status code: 0",
+        "comparison": "literal"
+      }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/responsebid.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/responsebid.json
new file mode 100644
index 00000000..c03aa1b2
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/responsebid.json
@@ -0,0 +1,79 @@
+{
+  "mockBidRequest": {
+      "id": "testid",
+      "site": {
+          "id": "test"
+      },
+      "imp": [
+          {
+              "id": "testimpid",
+              "banner": {
+                  "format": [
+                      {
+                          "w": 320,
+                          "h": 250
+                      },
+                      {
+                          "w": 320,
+                          "h": 300
+                      }
+                  ],
+                  "w": 320,
+                  "h": 250
+              },
+              "ext": {
+                  "bidder": {
+                      "pubid": "yu",
+                      "placement": "dummyplacement"
+                  }
+              }
+          }
+      ]
+  },
+  "httpCalls": [
+      {
+          "expectedRequest": {
+              "uri": "http://rtb.ninthdecimal.com/xp/get?pubid=yu",
+              "body": {
+                  "id": "testid",
+                  "imp": [
+                      {
+                          "banner": {
+                              "format": [
+                                  {
+                                      "h": 250,
+                                      "w": 320
+                                  },
+                                  {
+                                      "h": 300,
+                                      "w": 320
+                                  }
+                              ],
+                              "h": 250,
+                              "w": 320
+                          },
+                          "id": "testimpid",
+                          "tagid": "dummyplacement"
+                      }
+                  ],
+                  "site": {
+                      "id": "test"
+                  }
+              }
+          },
+          "mockResponse": {
+            "status":200,
+            "body": {
+                "seatbid": []
+            }
+        }
+    }
+
+  ],
+  "expectedMakeBidsErrors": [
+    {
+        "value": "Invalid SeatBids count: 0",
+        "comparison": "literal"
+      }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/site.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/site.json
new file mode 100644
index 00000000..a3e160e4
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/site.json
@@ -0,0 +1,103 @@
+{
+  "mockBidRequest": {
+      "id": "testid",
+      "site": {
+          "id": "test"
+      },
+      "imp": [
+          {
+              "id": "testimpid",
+              "banner": {
+                  "format": [
+                      {
+                          "w": 320,
+                          "h": 250
+                      },
+                      {
+                          "w": 320,
+                          "h": 300
+                      }
+                  ],
+                  "w": 320,
+                  "h": 250
+              },
+              "ext": {
+                  "bidder": {
+                      "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+                      "placement": "dummyplacement"
+                  }
+              }
+          }
+      ]
+  },
+  "httpCalls": [
+      {
+          "expectedRequest": {
+              "uri": "http://rtb.ninthdecimal.com/xp/get?pubid=19f1b372c7548ec1fe734d2c9f8dc688",
+              "body": {
+                  "id": "testid",
+                  "imp": [
+                      {
+                          "banner": {
+                              "format": [
+                                  {
+                                      "h": 250,
+                                      "w": 320
+                                  },
+                                  {
+                                      "h": 300,
+                                      "w": 320
+                                  }
+                              ],
+                              "h": 250,
+                              "w": 320
+                          },
+                          "id": "testimpid",
+                          "tagid": "dummyplacement"
+                      }
+                  ],
+                  "site": {
+                      "id": "test"
+                  }
+              }
+          },
+          "mockResponse": {
+              "status": 200,
+              "body": {
+                  "seatbid": [
+                      {
+                          "bid": [
+                              {
+                                  "crid": "24080",
+                                  "adid": "2068416",
+                                  "price": 0.01,
+                                  "id": "testid",
+                                  "impid": "testimpid",
+                                  "cid": "8048"
+                              }
+                          ]
+                      }
+                  ]
+              }
+          }
+      }
+  ],
+  "expectedBidResponses": [
+      {
+          "currency": "USD",
+          "bids": [
+              {
+                  "bid": {
+                      "crid": "24080",
+                      "adid": "2068416",
+                      "price": 0.01,
+                      "id": "testid",
+                      "impid": "testimpid",
+                      "cid": "8048"
+                  },
+                  "type": "banner"
+              }
+          ]
+      }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/ninthdecimaltest/supplemental/size.json b/adapters/ninthdecimal/ninthdecimaltest/supplemental/size.json
new file mode 100644
index 00000000..77228559
--- /dev/null
+++ b/adapters/ninthdecimal/ninthdecimaltest/supplemental/size.json
@@ -0,0 +1,28 @@
+{
+  "mockBidRequest": {
+    "id": "testid",
+    "site": {
+      "id": "test",
+      "domain": "test.com"
+    },
+    "imp": [
+      {
+        "id": "testimpid",
+        "banner": {
+          
+        },
+        "ext": {
+          "bidder": {
+            "pubid": "19f1b372c7548ec1fe734d2c9f8dc688",
+            "placement": "dummyplacement"
+          }
+        }
+      }
+    ]
+  },
+  "expectedMakeRequestsErrors": [
+    {
+        "value": "Expected at least one banner.format entry or explicit w/h",
+        "comparison": "literal"
+    }]
+}
\ No newline at end of file
diff --git a/adapters/ninthdecimal/params_test.go b/adapters/ninthdecimal/params_test.go
new file mode 100755
index 00000000..8d3ef3d7
--- /dev/null
+++ b/adapters/ninthdecimal/params_test.go
@@ -0,0 +1,45 @@
+package ninthdecimal
+
+import (
+	"encoding/json"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"testing"
+)
+
+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.BidderNinthDecimal, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected NinthDecimal params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderNinthDecimal, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"pubid": "19f1b372c7548ec1fe734d2c9f8dc688"}`,
+}
+
+var invalidParams = []string{
+	`{"publisher": "19f1b372c7548ec1fe734d2c9f8dc688"}`,
+	`nil`,
+	``,
+	`[]`,
+	`true`,
+}
diff --git a/adapters/ninthdecimal/usersync_test.go b/adapters/ninthdecimal/usersync_test.go
new file mode 100755
index 00000000..ee121434
--- /dev/null
+++ b/adapters/ninthdecimal/usersync_test.go
@@ -0,0 +1,31 @@
+package ninthdecimal
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNinthDecimalSyncer(t *testing.T) {
+	syncURL := "https://rtb.ninthdecimal.com/xp/user-sync?acctid={aid}&&redirect=localhost/setuid?bidder=ninthdecimal&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&uid=$UID"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewNinthDecimalSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "1",
+			Consent: "A",
+		},
+	})
+
+	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/rubicon/rubicon_test.go b/adapters/rubicon/rubicon_test.go
index d386daed..96623659 100644
--- a/adapters/rubicon/rubicon_test.go
+++ b/adapters/rubicon/rubicon_test.go
@@ -7,6 +7,7 @@ import (
 	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
+	"strconv"
 	"testing"
 	"time"
 
@@ -1133,6 +1134,48 @@ func TestOpenRTBRequestWithImpAndAdSlotIncluded(t *testing.T) {
 		"Unexpected dfp_ad_unit_code: %s", rubiconExtInventory["dfp_ad_unit_code"])
 }
 
+func TestOpenRTBRequestWithBadvOverflowed(t *testing.T) {
+	SIZE_ID := getTestSizes()
+	bidder := new(RubiconAdapter)
+
+	badvOverflowed := make([]string, 100)
+	for i := range badvOverflowed {
+		badvOverflowed[i] = strconv.Itoa(i)
+	}
+
+	request := &openrtb.BidRequest{
+		ID:   "test-request-id",
+		BAdv: badvOverflowed,
+		Imp: []openrtb.Imp{{
+			ID: "test-imp-id",
+			Banner: &openrtb.Banner{
+				Format: []openrtb.Format{
+					SIZE_ID[15],
+				},
+			},
+			Ext: json.RawMessage(`{
+				"bidder": {
+					"zoneId": 8394,
+					"siteId": 283282,
+					"accountId": 7891,
+					"inventory": {"key1" : "val1"},
+					"visitor": {"key2" : "val2"}
+				}
+			}`),
+		}},
+	}
+
+	reqs, _ := bidder.MakeRequests(request, &adapters.ExtraRequestInfo{})
+
+	rubiconReq := &openrtb.BidRequest{}
+	if err := json.Unmarshal(reqs[0].Body, rubiconReq); err != nil {
+		t.Fatalf("Unexpected error while decoding request: %s", err)
+	}
+
+	badvRequest := rubiconReq.BAdv
+	assert.Equal(t, badvOverflowed[:50], badvRequest, "Unexpected dfp_ad_unit_code: %s")
+}
+
 func TestOpenRTBRequestWithSpecificExtUserEids(t *testing.T) {
 	SIZE_ID := getTestSizes()
 	bidder := new(RubiconAdapter)
diff --git a/adapters/sharethrough/butler_test.go b/adapters/sharethrough/butler_test.go
index 673e1721..40c59b50 100644
--- a/adapters/sharethrough/butler_test.go
+++ b/adapters/sharethrough/butler_test.go
@@ -2,17 +2,18 @@ package sharethrough
 
 import (
 	"fmt"
-	"github.com/mxmCherry/openrtb"
-	"github.com/prebid/prebid-server/adapters"
-	"github.com/prebid/prebid-server/errortypes"
-	"github.com/prebid/prebid-server/openrtb_ext"
-	"github.com/stretchr/testify/assert"
 	"net/http"
 	"regexp"
 	"strconv"
 	"strings"
 	"testing"
 	"time"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"github.com/stretchr/testify/assert"
 )
 
 type MockUtil struct {
@@ -538,15 +539,15 @@ func TestFailParseUri(t *testing.T) {
 	}{
 		"Fails decoding if unable to parse URI": {
 			input:         "test:/#$%?#",
-			expectedError: `parse test:/#$%?#: invalid URL escape "%?#"`,
+			expectedError: `parse (\")?test:/#\$%\?#(\")?: invalid URL escape \"%\?#\"`,
 		},
 		"Fails decoding if height not provided": {
 			input:         "http://abc.com?width=10",
-			expectedError: `strconv.ParseUint: parsing "": invalid syntax`,
+			expectedError: `strconv.ParseUint: parsing \"\": invalid syntax`,
 		},
 		"Fails decoding if width not provided": {
 			input:         "http://abc.com?height=10",
-			expectedError: `strconv.ParseUint: parsing "": invalid syntax`,
+			expectedError: `strconv.ParseUint: parsing \"\": invalid syntax`,
 		},
 	}
 
@@ -559,6 +560,6 @@ func TestFailParseUri(t *testing.T) {
 
 		assert.Nil(output)
 		assert.NotNil(actualError)
-		assert.Equal(test.expectedError, actualError.Error())
+		assert.Regexp(test.expectedError, actualError.Error())
 	}
 }
diff --git a/adapters/tappx/tappxtest/supplemental/banner-impression-badhost.json b/adapters/tappx/tappxtest/supplemental/banner-impression-badhost.json
index 811f34f3..c82d0e85 100644
--- a/adapters/tappx/tappxtest/supplemental/banner-impression-badhost.json
+++ b/adapters/tappx/tappxtest/supplemental/banner-impression-badhost.json
@@ -31,8 +31,8 @@
 
   "expectedMakeRequestsErrors": [
     {
-      "value": "Malformed URL: parse https://example.ho%st.tappx.com: invalid URL escape \"%st\"",
-      "comparison": "literal"
+      "value": "Malformed URL: parse (\\\")?https://example\\.ho%st\\.tappx.com(\\\")?: invalid URL escape \\\"%st\\\"",
+      "comparison": "regex"
     }
   ]
  
diff --git a/adapters/telaria/params_test.go b/adapters/telaria/params_test.go
new file mode 100644
index 00000000..efa3fba1
--- /dev/null
+++ b/adapters/telaria/params_test.go
@@ -0,0 +1,50 @@
+package telaria
+
+import (
+	"encoding/json"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"testing"
+)
+
+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.BidderTelaria, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected Telaria params: %s", validParam)
+		}
+	}
+}
+
+// TestInvalidParams makes sure that the Telaria 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.BidderTelaria, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"adCode": "string", "seatCode": "string", "originalPublisherid": "string"}`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"adCode": "string", "originalPublisherid": "string"}`,
+	`{"adCode": "string", "seatCode": 5, "originalPublisherid": "string"}`,
+}
diff --git a/adapters/telaria/telaria_test.go b/adapters/telaria/telaria_test.go
new file mode 100644
index 00000000..7ad96b93
--- /dev/null
+++ b/adapters/telaria/telaria_test.go
@@ -0,0 +1,34 @@
+package telaria
+
+import (
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"testing"
+)
+
+/**
+ * Verify adapter names are setup correctly.
+ */
+func TestTelariaAdapterNames(t *testing.T) {
+	adapter := NewTelariaBidder("")
+	adapterstest.VerifyStringValue(adapter.Name(), "telaria", t)
+}
+
+/**
+ * Verify adapter SkipNoCookie is correct.
+ */
+func TestTelariaAdapterSkipNoCookiesFlag(t *testing.T) {
+	adapter := NewTelariaBidder("")
+	adapterstest.VerifyBoolValue(adapter.SkipNoCookies(), false, t)
+}
+
+/**
+ * Verify bidder has the proper URL
+ */
+func TestTelariaAdapterEndpoint(t *testing.T) {
+	adapter := NewTelariaBidder("")
+	adapterstest.VerifyStringValue(adapter.URI, "https://ads.tremorhub.com/ad/rtb/prebid", t)
+}
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "telariatest", NewTelariaBidder(""))
+}
diff --git a/adapters/telaria/telariatest/exemplary/video-app.json b/adapters/telaria/telariatest/exemplary/video-app.json
new file mode 100644
index 00000000..09bcf998
--- /dev/null
+++ b/adapters/telaria/telariatest/exemplary/video-app.json
@@ -0,0 +1,157 @@
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB22-1"
+      ],
+      "bundle": "com.app.awesome",
+      "name": "Awesome App",
+      "domain": "awesomeapp.com",
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": ["application/json;charset=utf-8"],
+        "Accept": ["application/json"],
+        "X-Openrtb-Version": ["2.5"],
+        "Accept-Encoding": ["gzip"],
+        "User-Agent": ["test-user-agent"],
+        "X-Forwarded-For": ["123.123.123.123"],
+        "Accept-Language": ["en"],
+        "Dnt": ["0"]
+      },
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "device": {
+          "ua": "test-user-agent",
+          "ip": "123.123.123.123",
+          "language": "en",
+          "dnt": 0
+        },
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "tagid": "my-adcode",
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": "123456789"
+            }
+          }
+        ],
+        "app": {
+          "id": "123456789",
+          "name": "Awesome App",
+          "bundle": "com.app.awesome",
+          "domain": "awesomeapp.com",
+          "cat": [
+            "IAB22-1"
+          ],
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "awesome-resp-id",
+        "seatbid": [{
+          "bid": [{
+            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+            "impid": "1",
+            "price": 3.5,
+            "adm": "asesome-markup",
+            "adomain": [
+              "awesome.com"
+            ],
+            "crid": "20",
+            "w": 1280,
+            "h": 720,
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          }],
+          "seat": "telaria"
+        }],
+        "cur": "USD",
+        "ext": {
+          "responsetimemillis": {
+            "telaria": 154
+          },
+          "tmaxrequest": 1000
+        }
+      }
+    }
+  }],
+  "expectedBids": [{
+    "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+    "impid": "1",
+    "price": 3.5,
+    "adm": "awesome-markup",
+    "adomain": [
+      "awesome.com"
+    ],
+    "crid": "20",
+    "w": 1280,
+    "h": 720,
+    "ext": {
+      "prebid": {
+        "type": "video"
+      }
+    }
+  }]
+}
diff --git a/adapters/telaria/telariatest/exemplary/video-web.json b/adapters/telaria/telariatest/exemplary/video-web.json
new file mode 100644
index 00000000..5dc26b0f
--- /dev/null
+++ b/adapters/telaria/telariatest/exemplary/video-web.json
@@ -0,0 +1,145 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "site": {
+      "page": "test.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": ["application/json;charset=utf-8"],
+        "Accept": ["application/json"],
+        "X-Openrtb-Version": ["2.5"],
+        "Accept-Encoding": ["gzip"],
+        "User-Agent": ["test-user-agent"],
+        "X-Forwarded-For": ["123.123.123.123"],
+        "Accept-Language": ["en"],
+        "Dnt": ["0"]
+      },
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "device": {
+          "ua": "test-user-agent",
+          "ip": "123.123.123.123",
+          "language": "en",
+          "dnt": 0
+        },
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "my-adcode",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": "123456789"
+            }
+          }
+        ],
+        "site": {
+          "page": "test.com",
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": {
+        "id": "awesome-resp-id",
+        "seatbid": [{
+          "bid": [{
+            "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+            "impid": "1",
+            "price": 3.5,
+            "adm": "asesome-markup",
+            "adomain": [
+              "awesome.com"
+            ],
+            "crid": "20",
+            "w": 1280,
+            "h": 720,
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          }],
+          "seat": "telaria"
+        }],
+        "cur": "USD",
+        "ext": {
+          "responsetimemillis": {
+            "telaria": 154
+          },
+          "tmaxrequest": 1000
+        }
+      }
+    }
+  }],
+  "expectedBids": [{
+    "id": "a3ae1b4e2fc24a4fb45540082e98e161",
+    "impid": "1",
+    "price": 3.5,
+    "adm": "asesome-markup",
+    "adomain": [
+      "awesome.com"
+    ],
+    "crid": "20",
+    "w": 1280,
+    "h": 720,
+    "ext": {
+      "prebid": {
+        "type": "video"
+      }
+    }
+  }]
+}
diff --git a/adapters/telaria/telariatest/params/race/video.json b/adapters/telaria/telariatest/params/race/video.json
new file mode 100644
index 00000000..e3b67ec8
--- /dev/null
+++ b/adapters/telaria/telariatest/params/race/video.json
@@ -0,0 +1,4 @@
+{
+  "adCode": "my-adcode",
+  "seatCode": "my-seatcode"
+}
diff --git a/adapters/telaria/telariatest/supplemental/banner-unsupported.json b/adapters/telaria/telariatest/supplemental/banner-unsupported.json
new file mode 100644
index 00000000..1e75371d
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/banner-unsupported.json
@@ -0,0 +1,42 @@
+
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Telaria: Banner not supported",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "site": {
+      "page": "test.com",
+      "publisher": {
+        "id": "someother-publisher-id"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "my-adcode",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/adapters/telaria/telariatest/supplemental/invalid-response.json b/adapters/telaria/telariatest/supplemental/invalid-response.json
new file mode 100644
index 00000000..8e4f1ee8
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/invalid-response.json
@@ -0,0 +1,105 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "device": {
+      "ua": "test-user-agent",
+      "ip": "123.123.123.123",
+      "language": "en",
+      "dnt": 0
+    },
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "site": {
+      "page": "test.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": ["application/json;charset=utf-8"],
+        "Accept": ["application/json"],
+        "X-Openrtb-Version": ["2.5"],
+        "Accept-Encoding": ["gzip"],
+        "User-Agent": ["test-user-agent"],
+        "X-Forwarded-For": ["123.123.123.123"],
+        "Accept-Language": ["en"],
+        "Dnt": ["0"]
+      },
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "device": {
+          "ua": "test-user-agent",
+          "ip": "123.123.123.123",
+          "language": "en",
+          "dnt": 0
+        },
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "my-adcode",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": "123456789"
+            }
+          }
+        ],
+        "site": {
+          "page": "test.com",
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": "invalid response"
+    }
+  }],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Telaria: Bad Server Response",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/telaria/telariatest/supplemental/invalid-telaria-ext-object.json b/adapters/telaria/telariatest/supplemental/invalid-telaria-ext-object.json
new file mode 100644
index 00000000..efdec8ad
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/invalid-telaria-ext-object.json
@@ -0,0 +1,29 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Telaria: ext.bidder not provided",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "my-adcode",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": "Awesome"
+      }
+    ],
+    "site": {
+      "page": "test.com"
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/telaria/telariatest/supplemental/requires-imp-object.json b/adapters/telaria/telariatest/supplemental/requires-imp-object.json
new file mode 100644
index 00000000..5933dc4e
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/requires-imp-object.json
@@ -0,0 +1,16 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Telaria: Missing Imp Object",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [],
+    "site": {
+      "page": "test.com"
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/telaria/telariatest/supplemental/requires-seat-code.json b/adapters/telaria/telariatest/supplemental/requires-seat-code.json
new file mode 100644
index 00000000..5c05e529
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/requires-seat-code.json
@@ -0,0 +1,30 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Telaria: Seat Code required",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-impression-1",
+        "video": {
+          "w": 640,
+          "h": 480,
+          "linearity": 1
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode"
+          }
+        }
+      }
+    ],
+    "site": {
+      "page": "test.com"
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/telaria/telariatest/supplemental/requires-video-object.json b/adapters/telaria/telariatest/supplemental/requires-video-object.json
new file mode 100644
index 00000000..3f797c9e
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/requires-video-object.json
@@ -0,0 +1,26 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Telaria: Only Supports Video",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-impression-1",
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ],
+    "site": {
+      "page": "test.com"
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/telaria/telariatest/supplemental/status-code-bad-request.json b/adapters/telaria/telariatest/supplemental/status-code-bad-request.json
new file mode 100644
index 00000000..0b5d8a85
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/status-code-bad-request.json
@@ -0,0 +1,80 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "app": {
+      "id": "123456789"
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "my-adcode",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": ""
+            }
+          }
+        ],
+        "app": {
+          "id": "123456789",
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 400
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Telaria: Unexpected status code: [ 400 ] ",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/telaria/telariatest/supplemental/status-code-no-content.json b/adapters/telaria/telariatest/supplemental/status-code-no-content.json
new file mode 100644
index 00000000..ffb183f4
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/status-code-no-content.json
@@ -0,0 +1,83 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "site": {
+      "page": "test.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "my-adcode",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": "123456789"
+            }
+          }
+        ],
+        "site": {
+          "page": "test.com",
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 204
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Telaria: Invalid Bid Request received by the server",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/telaria/telariatest/supplemental/status-code-other-error.json b/adapters/telaria/telariatest/supplemental/status-code-other-error.json
new file mode 100644
index 00000000..15e4b7f8
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/status-code-other-error.json
@@ -0,0 +1,83 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "site": {
+      "page": "test.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "my-adcode",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": "123456789"
+            }
+          }
+        ],
+        "site": {
+          "page": "test.com",
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 306
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Telaria: Something went wrong, please contact your Account Manager. Status Code: [ 306 ] ",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/telaria/telariatest/supplemental/status-code-service-unavailable.json b/adapters/telaria/telariatest/supplemental/status-code-service-unavailable.json
new file mode 100644
index 00000000..b92d4ea8
--- /dev/null
+++ b/adapters/telaria/telariatest/supplemental/status-code-service-unavailable.json
@@ -0,0 +1,83 @@
+
+{
+  "mockBidRequest": {
+    "id": "some-request-id",
+    "tmax": 1000,
+    "user": {
+      "buyeruid": "awesome-user"
+    },
+    "site": {
+      "page": "test.com",
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "imp": [
+      {
+        "id": "some-impression-id",
+        "tagid": "ogTAGID",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 120,
+          "maxduration": 150
+        },
+        "ext": {
+          "bidder": {
+            "adCode": "my-adcode",
+            "seatCode": "my-seatcode"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "https://ads.tremorhub.com/ad/rtb/prebid",
+      "body": {
+        "id": "some-request-id",
+        "imp": [
+          {
+            "id": "some-impression-id",
+            "tagid": "my-adcode",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 120,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "ext": {
+              "originalTagid": "ogTAGID",
+              "originalPublisherid": "123456789"
+            }
+          }
+        ],
+        "site": {
+          "page": "test.com",
+          "publisher": {
+            "id": "my-seatcode"
+          }
+        },
+        "user": {
+          "buyeruid": "awesome-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 503
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Telaria: Something went wrong, please contact your Account Manager. Status Code: [ 503 ] ",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/telaria/usersync_test.go b/adapters/telaria/usersync_test.go
new file mode 100644
index 00000000..4896b253
--- /dev/null
+++ b/adapters/telaria/usersync_test.go
@@ -0,0 +1,33 @@
+package telaria
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestTelariaSyncer(t *testing.T) {
+
+	syncURL := "https://pbs.publishers.tremorhub.com/pubsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewTelariaSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal: "0",
+		},
+	})
+
+	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/yieldone/params_test.go b/adapters/yieldone/params_test.go
new file mode 100644
index 00000000..6048ea5d
--- /dev/null
+++ b/adapters/yieldone/params_test.go
@@ -0,0 +1,48 @@
+package yieldone
+
+import (
+	"encoding/json"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"testing"
+)
+
+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.BidderYieldone, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected Yieldone params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderYieldone, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"placementId": "123"}`,
+}
+
+var invalidParams = []string{
+	`null`,
+	`nil`,
+	``,
+	`[]`,
+	`true`,
+	`2`,
+	`{"invalid_param": "123"}`,
+	`{"placementId": 123}`,
+}
diff --git a/adapters/yieldone/usersync_test.go b/adapters/yieldone/usersync_test.go
new file mode 100644
index 00000000..902f3b66
--- /dev/null
+++ b/adapters/yieldone/usersync_test.go
@@ -0,0 +1,30 @@
+package yieldone
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestYieldoneSyncer(t *testing.T) {
+	syncURL := "//not_localhost/synclocalhost%2Fsetuid%3Fbidder%3Dyieldone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewYieldoneSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal: "0",
+		},
+	})
+
+	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/adapters/yieldone/yieldone_test.go b/adapters/yieldone/yieldone_test.go
new file mode 100644
index 00000000..34d58baf
--- /dev/null
+++ b/adapters/yieldone/yieldone_test.go
@@ -0,0 +1,11 @@
+package yieldone
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "yieldonetest", NewYieldoneBidder("http://localhost/prebid"))
+}
diff --git a/adapters/yieldone/yieldonetest/exemplary/simple-banner.json b/adapters/yieldone/yieldonetest/exemplary/simple-banner.json
new file mode 100644
index 00000000..f84476f1
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/exemplary/simple-banner.json
@@ -0,0 +1,89 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "site": {
+            "page": "https://good.site/url"
+        },
+        "imp": [{
+            "id": "test-imp-id",
+            "banner": {
+                "format": [{
+                    "w": 300,
+                    "h": 250
+                }]
+            },
+            "ext": {
+                "bidder": {
+                    "placementId": "36891"
+                }
+            }
+        }]
+    },
+
+    "httpCalls": [{
+        "expectedRequest": {
+            "uri": "http://localhost/prebid",
+            "body": {
+                "id": "test-request-id",
+                "site": {
+                    "page": "https://good.site/url"
+                },
+                "imp": [{
+                    "id": "test-imp-id",
+                    "banner": {
+                        "format": [{
+                            "w": 300,
+                            "h": 250
+                        }],
+                        "w": 300,
+                        "h": 250
+                    },
+                    "ext": {
+                        "bidder": {
+                            "placementId": "36891"
+                        }
+                    }
+                }]
+            }
+        },
+        "mockResponse": {
+            "status": 200,
+            "body": {
+                "id": "test-request-id",
+                "seatbid": [{
+                    "seat": "yieldone",
+                    "bid": [{
+                        "id": "randomid",
+                        "impid": "test-imp-id",
+                        "price": 0.500000,
+                        "adid": "12345678",
+                        "adm": "some-test-ad",
+                        "cid": "987",
+                        "crid": "12345678",
+                        "h": 250,
+                        "w": 300
+                    }]
+                }],
+                "cur": "JPY"
+            }
+        }
+    }],
+
+    "expectedBidResponses": [{
+        "currency": "JPY",
+        "bids": [{
+            "bid": {
+                "id": "randomid",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-test-ad",
+                "adid": "12345678",
+                "cid": "987",
+                "crid": "12345678",
+                "w": 300,
+                "h": 250
+            },
+            "type": "banner"
+        }]
+    }]
+}
diff --git a/adapters/yieldone/yieldonetest/exemplary/simple-video.json b/adapters/yieldone/yieldonetest/exemplary/simple-video.json
new file mode 100644
index 00000000..dc313abe
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/exemplary/simple-video.json
@@ -0,0 +1,87 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "site": {
+            "page": "https://good.site/url"
+        },
+        "imp": [{
+            "id": "test-imp-id",
+            "video": {
+                "mimes": ["video/mp4"],
+                "protocols": [2, 5],
+                "w": 300,
+                "h": 250
+            },
+            "ext": {
+                "bidder": {
+                    "placementId": "41993"
+                }
+            }
+        }]
+    },
+
+    "httpCalls": [{
+        "expectedRequest": {
+            "uri": "http://localhost/prebid",
+            "body": {
+                "id": "test-request-id",
+                "site": {
+                    "page": "https://good.site/url"
+                },
+                "imp": [{
+                    "id": "test-imp-id",
+                    "video": {
+                        "mimes": ["video/mp4"],
+                        "protocols": [2, 5],
+                        "w": 300,
+                        "h": 250
+                    },
+                    "ext": {
+                        "bidder": {
+                            "placementId": "41993"
+                        }
+                    }
+                }]
+            }
+        },
+        "mockResponse": {
+            "status": 200,
+            "body": {
+                "id": "test-request-id",
+                "seatbid": [{
+                    "seat": "yieldone",
+                    "bid": [{
+                        "id": "randomid",
+                        "impid": "test-imp-id",
+                        "price": 0.500000,
+                        "adid": "12345678",
+                        "adm": "some-test-ad-vast",
+                        "cid": "987",
+                        "crid": "12345678",
+                        "h": 250,
+                        "w": 300
+                    }]
+                }],
+                "cur": "JPY"
+            }
+        }
+    }],
+
+    "expectedBidResponses": [{
+        "currency": "JPY",
+        "bids": [{
+            "bid": {
+                "id": "randomid",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-test-ad-vast",
+                "adid": "12345678",
+                "cid": "987",
+                "crid": "12345678",
+                "w": 300,
+                "h": 250
+            },
+            "type": "video"
+        }]
+    }]
+}
diff --git a/adapters/yieldone/yieldonetest/params/race/banner.json b/adapters/yieldone/yieldonetest/params/race/banner.json
new file mode 100644
index 00000000..c8818084
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/params/race/banner.json
@@ -0,0 +1,4 @@
+{
+  "placementId": "36891"
+}
+
diff --git a/adapters/yieldone/yieldonetest/supplemental/bad_response.json b/adapters/yieldone/yieldonetest/supplemental/bad_response.json
new file mode 100644
index 00000000..fa993a2f
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/supplemental/bad_response.json
@@ -0,0 +1,65 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "placementId": "36891"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ],
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "placementId": "36891"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": "{\"id\"data.lost"
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "json: cannot unmarshal string into Go value of type openrtb.BidResponse",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/yieldone/yieldonetest/supplemental/status_204.json b/adapters/yieldone/yieldonetest/supplemental/status_204.json
new file mode 100644
index 00000000..b1c9304a
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/supplemental/status_204.json
@@ -0,0 +1,60 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "placementId": "36891"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ],
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "placementId": "36891"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedBidResponses": []
+}
diff --git a/adapters/yieldone/yieldonetest/supplemental/status_400.json b/adapters/yieldone/yieldonetest/supplemental/status_400.json
new file mode 100644
index 00000000..1cb172bb
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/supplemental/status_400.json
@@ -0,0 +1,65 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "placementId": "36891"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ],
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "placementId": "36891"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 400,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/yieldone/yieldonetest/supplemental/status_418.json b/adapters/yieldone/yieldonetest/supplemental/status_418.json
new file mode 100644
index 00000000..30cc16ad
--- /dev/null
+++ b/adapters/yieldone/yieldonetest/supplemental/status_418.json
@@ -0,0 +1,65 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "placementId": "36891"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://localhost/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ],
+                "w": 300,
+                "h": 250
+              },
+              "ext": {
+                "bidder": {
+                  "placementId": "36891"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 418,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 418. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/config/config_test.go b/config/config_test.go
index 9677ce2a..92794d79 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -270,6 +270,8 @@ func TestFullConfig(t *testing.T) {
 	cmpStrings(t, "adapters.audiencenetwork.usersync_url", cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderFacebook))].UserSyncURL, "http://facebook.com/ortb/prebid-s2s")
 	cmpStrings(t, "adapters.audiencenetwork.platform_id", cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderFacebook))].PlatformID, "abcdefgh1234")
 	cmpStrings(t, "adapters.audiencenetwork.app_secret", cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderFacebook))].AppSecret, "987abc")
+	cmpStrings(t, "adapters.beachfront.endpoint", cfg.Adapters[string(openrtb_ext.BidderBeachfront)].Endpoint, "https://display.bfmio.com/prebid_display")
+	cmpStrings(t, "adapters.beachfront.extra_info", cfg.Adapters[string(openrtb_ext.BidderBeachfront)].ExtraAdapterInfo, "{\"video_endpoint\":\"https://reachms.bfmio.com/bid.json?exchange_id\"}")
 	cmpStrings(t, "adapters.ix.endpoint", cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderIx))].Endpoint, "http://ixtest.com/api")
 	cmpStrings(t, "adapters.rubicon.endpoint", cfg.Adapters[string(openrtb_ext.BidderRubicon)].Endpoint, "http://rubitest.com/api")
 	cmpStrings(t, "adapters.rubicon.usersync_url", cfg.Adapters[string(openrtb_ext.BidderRubicon)].UserSyncURL, "http://pixel.rubiconproject.com/sync.php?p=prebid")
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index d0ce33de..ec525c6f 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -927,6 +927,49 @@ func TestParseVideoRequestWithoutUserAgentAndEmptyHeader(t *testing.T) {
 
 }
 
+func TestParseVideoRequestWithEncodedUserAgentInHeader(t *testing.T) {
+	ex := &mockExchangeVideo{}
+	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_without_device_user_agent.json")
+	if err != nil {
+		t.Fatalf("Failed to fetch a valid request: %v", err)
+	}
+
+	uaEncoded := "Mozilla%2F5.0%20%28Macintosh%3B%20Intel%20Mac%20OS%20X%2010_14_6%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F78.0.3904.87%20Safari%2F537.36"
+	uaDecoded := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
+
+	headers := http.Header{}
+	headers.Add("User-Agent", uaEncoded)
+
+	deps := mockDeps(t, ex)
+	req, valErr, podErr := deps.parseVideoRequest(reqData, headers)
+
+	assert.Equal(t, uaDecoded, req.Device.UA, "Device.ua should be taken from request header")
+	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
+	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
+
+}
+
+func TestParseVideoRequestWithDecodedUserAgentInHeader(t *testing.T) {
+	ex := &mockExchangeVideo{}
+	reqData, err := ioutil.ReadFile("sample-requests/video/video_valid_sample_without_device_user_agent.json")
+	if err != nil {
+		t.Fatalf("Failed to fetch a valid request: %v", err)
+	}
+
+	uaDecoded := "Mozilla/5.0+(Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
+
+	headers := http.Header{}
+	headers.Add("User-Agent", uaDecoded)
+
+	deps := mockDeps(t, ex)
+	req, valErr, podErr := deps.parseVideoRequest(reqData, headers)
+
+	assert.Equal(t, uaDecoded, req.Device.UA, "Device.ua should be taken from request header")
+	assert.Equal(t, []error(nil), valErr, "No validation errors should be returned")
+	assert.Equal(t, make([]PodError, 0), podErr, "No pod errors should be returned")
+
+}
+
 func TestHandleErrorDebugLog(t *testing.T) {
 	vo := analytics.VideoObject{
 		Status: 200,
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index 46f63cc6..f20b431c 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -15,6 +15,9 @@ import (
 	"github.com/prebid/prebid-server/currencies"
 	"github.com/prebid/prebid-server/openrtb_ext"
 	"github.com/stretchr/testify/assert"
+
+	nativeRequests "github.com/mxmCherry/openrtb/native/request"
+	nativeResponse "github.com/mxmCherry/openrtb/native/response"
 )
 
 // TestSingleBidder makes sure that the following things work if the Bidder needs only one request.
@@ -1083,6 +1086,147 @@ func TestErrorReporting(t *testing.T) {
 	}
 }
 
+func TestSetAssetTypes(t *testing.T) {
+	testCases := []struct {
+		respAsset   nativeResponse.Asset
+		nativeReq   nativeRequests.Request
+		expectedErr string
+		desc        string
+	}{
+		{
+			respAsset: nativeResponse.Asset{
+				ID: 1,
+				Img: &nativeResponse.Image{
+					URL: "http://some-url",
+				},
+			},
+			nativeReq: nativeRequests.Request{
+				Assets: []nativeRequests.Asset{
+					{
+						ID: 1,
+						Img: &nativeRequests.Image{
+							Type: 2,
+						},
+					},
+					{
+						ID: 2,
+						Data: &nativeRequests.Data{
+							Type: 4,
+						},
+					},
+				},
+			},
+			expectedErr: "",
+			desc:        "Matching image asset exists in the request and asset type is set correctly",
+		},
+		{
+			respAsset: nativeResponse.Asset{
+				ID: 2,
+				Data: &nativeResponse.Data{
+					Label: "some label",
+				},
+			},
+			nativeReq: nativeRequests.Request{
+				Assets: []nativeRequests.Asset{
+					{
+						ID: 1,
+						Img: &nativeRequests.Image{
+							Type: 2,
+						},
+					},
+					{
+						ID: 2,
+						Data: &nativeRequests.Data{
+							Type: 4,
+						},
+					},
+				},
+			},
+			expectedErr: "",
+			desc:        "Matching data asset exists in the request and asset type is set correctly",
+		},
+		{
+			respAsset: nativeResponse.Asset{
+				ID: 1,
+				Img: &nativeResponse.Image{
+					URL: "http://some-url",
+				},
+			},
+			nativeReq: nativeRequests.Request{
+				Assets: []nativeRequests.Asset{
+					{
+						ID: 2,
+						Img: &nativeRequests.Image{
+							Type: 2,
+						},
+					},
+				},
+			},
+			expectedErr: "Unable to find asset with ID:1 in the request",
+			desc:        "Matching image asset with the same ID doesn't exist in the request",
+		},
+		{
+			respAsset: nativeResponse.Asset{
+				ID: 2,
+				Data: &nativeResponse.Data{
+					Label: "some label",
+				},
+			},
+			nativeReq: nativeRequests.Request{
+				Assets: []nativeRequests.Asset{
+					{
+						ID: 2,
+						Img: &nativeRequests.Image{
+							Type: 2,
+						},
+					},
+				},
+			},
+			expectedErr: "Response has a Data asset with ID:2 present that doesn't exist in the request",
+			desc:        "Assets with same ID in the req and resp are of different types",
+		},
+		{
+			respAsset: nativeResponse.Asset{
+				ID: 1,
+				Img: &nativeResponse.Image{
+					URL: "http://some-url",
+				},
+			},
+			nativeReq: nativeRequests.Request{
+				Assets: []nativeRequests.Asset{
+					{
+						ID: 1,
+						Data: &nativeRequests.Data{
+							Type: 2,
+						},
+					},
+				},
+			},
+			expectedErr: "Response has an Image asset with ID:1 present that doesn't exist in the request",
+			desc:        "Assets with same ID in the req and resp are of different types",
+		},
+	}
+
+	for _, test := range testCases {
+		err := setAssetTypes(test.respAsset, test.nativeReq)
+		if len(test.expectedErr) != 0 {
+			assert.EqualError(t, err, test.expectedErr, "Test Case: %s", test.desc)
+			continue
+		} else {
+			assert.NoError(t, err, "Test Case: %s", test.desc)
+		}
+
+		for _, asset := range test.nativeReq.Assets {
+			if asset.Img != nil && test.respAsset.Img != nil {
+				assert.Equal(t, asset.Img.Type, test.respAsset.Img.Type, "Asset type not set correctly. Test Case: %s", test.desc)
+			}
+			if asset.Data != nil && test.respAsset.Data != nil {
+				assert.Equal(t, asset.Data.Type, test.respAsset.Data.Type, "Asset type not set correctly. Test Case: %s", test.desc)
+			}
+		}
+	}
+}
+
 type goodSingleBidder struct {
 	bidRequest   *openrtb.BidRequest
 	httpRequest  *adapters.RequestData
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 2f115ca4..3c1c2f3b 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -483,6 +483,11 @@ func TestRaceIntegration(t *testing.T) {
 		Endpoint:   server.URL,
 		PlatformID: "abc",
 	}
+	cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderBeachfront))] = config.Adapter{
+		Endpoint:         server.URL,
+		ExtraAdapterInfo: "{\"video_endpoint\":\"" + server.URL + "\"}",
+	}
+
 	categoriesFetcher, error := newCategoryFetcher("./test/category-mapping")
 	if error != nil {
 		t.Errorf("Failed to create a category Fetcher: %v", error)
@@ -766,6 +771,11 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 			}
 		}
 	}
+	if spec.IncomingRequest.OrtbRequest.Test == 1 {
+		//compare debug info
+		diffJson(t, "Debug info modified", bid.Ext, spec.Response.Ext)
+
+	}
 }
 
 func findBiddersInAuction(t *testing.T, context string, req *openrtb.BidRequest) []string {
@@ -1403,7 +1413,10 @@ func TestApplyDealSupport(t *testing.T) {
 			},
 		}
 
-		bid := pbsOrtbBid{&openrtb.Bid{}, "video", test.targ, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bidCategory := map[string]string{
+			bid.bid.ID: test.targ["hb_pb_cat_dur"],
+		}
 
 		auc := &auction{
 			winningBidsByBidder: map[string]map[openrtb_ext.BidderName]*pbsOrtbBid{
@@ -1413,9 +1426,9 @@ func TestApplyDealSupport(t *testing.T) {
 			},
 		}
 
-		dealErrs := applyDealSupport(bidRequest, auc)
+		dealErrs := applyDealSupport(bidRequest, auc, bidCategory)
 
-		assert.Equal(t, test.expectedHbPbCatDur, auc.winningBidsByBidder["imp_id1"][bidderName].bidTargets["hb_pb_cat_dur"], test.description)
+		assert.Equal(t, test.expectedHbPbCatDur, bidCategory[auc.winningBidsByBidder["imp_id1"][bidderName].bid.ID], test.description)
 		if len(test.expectedDealErr) > 0 {
 			assert.Containsf(t, dealErrs, errors.New(test.expectedDealErr), "Expected error message not found in deal errors")
 		}
@@ -1590,11 +1603,14 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 	}
 
 	for _, test := range testCases {
-		bid := pbsOrtbBid{&openrtb.Bid{}, "video", test.targ, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bidCategory := map[string]string{
+			bid.bid.ID: test.targ["hb_pb_cat_dur"],
+		}
 
-		updateHbPbCatDur(&bid, test.dealTier)
+		updateHbPbCatDur(&bid, test.dealTier, bidCategory)
 
-		assert.Equal(t, test.expectedHbPbCatDur, bid.bidTargets["hb_pb_cat_dur"], test.description)
+		assert.Equal(t, test.expectedHbPbCatDur, bidCategory[bid.bid.ID], test.description)
 	}
 }
 
@@ -1614,6 +1630,7 @@ type exchangeRequest struct {
 type exchangeResponse struct {
 	Bids  *openrtb.BidResponse `json:"bids"`
 	Error string               `json:"error,omitempty"`
+	Ext   json.RawMessage      `json:"ext,omitempty"`
 }
 
 type bidderSpec struct {
@@ -1627,8 +1644,9 @@ type bidderRequest struct {
 }
 
 type bidderResponse struct {
-	SeatBid *bidderSeatBid `json:"pbsSeatBid,omitempty"`
-	Errors  []string       `json:"errors,omitempty"`
+	SeatBid   *bidderSeatBid             `json:"pbsSeatBid,omitempty"`
+	Errors    []string                   `json:"errors,omitempty"`
+	HttpCalls []*openrtb_ext.ExtHttpCall `json:"httpCalls,omitempty"`
 }
 
 // bidderSeatBid is basically a subset of pbsOrtbSeatBid from exchange/bidder.go.
@@ -1685,7 +1703,13 @@ func (b *validatingBidder) requestBid(ctx context.Context, request *openrtb.BidR
 			}
 
 			seatBid = &pbsOrtbSeatBid{
-				bids: bids,
+				bids:      bids,
+				httpCalls: mockResponse.HttpCalls,
+			}
+		} else {
+			seatBid = &pbsOrtbSeatBid{
+				bids:      nil,
+				httpCalls: mockResponse.HttpCalls,
 			}
 		}
 
diff --git a/exchange/exchangetest/request-multi-bidders-debug-info.json b/exchange/exchangetest/request-multi-bidders-debug-info.json
new file mode 100644
index 00000000..ec174f75
--- /dev/null
+++ b/exchange/exchangetest/request-multi-bidders-debug-info.json
@@ -0,0 +1,227 @@
+{
+  "incomingRequest": {
+    "ortbRequest": {
+      "test": 1,
+      "id": "some-request-id",
+      "site": {
+        "page": "test.somepage.com"
+      },
+      "imp": [
+        {
+          "id": "my-imp-id",
+          "video": {
+            "mimes": [
+              "video/mp4"
+            ]
+          },
+          "ext": {
+            "appnexus": {
+              "placementId": 1
+            },
+            "audienceNetwork": {
+              "placementId": "some-placement"
+            }
+          }
+        },
+        {
+          "id": "imp-id-2",
+          "video": {
+            "mimes": [
+              "video/mp4"
+            ]
+          },
+          "ext": {
+            "appnexus": {
+              "placementId": 2
+            },
+            "audienceNetwork": {
+              "placementId": "some-other-placement"
+            }
+          }
+        }
+      ],
+      "ext": {
+        "prebid": {
+          "targeting": {
+            "durationRangeSec": [
+              15,
+              30
+            ],
+            "includebrandcategory": {
+              "primaryadserver": 1,
+              "publisher": "",
+              "withCategory": true,
+              "translateCategories": true
+            }
+          }
+        }
+      }
+    }
+  },
+  "outgoingRequests": {
+    "appnexus": {
+      "mockResponse": {
+        "httpCalls": [
+          {
+            "uri": "appnexusTest.com",
+            "requestbody": "appnexusTestRequestBody",
+            "responsebody": "appnexusTestResponseBody",
+            "status": 200
+          }
+        ],
+        "pbsSeatBid": {
+          "pbsBids": [
+            {
+              "ortbBid": {
+                "id": "winning-bid",
+                "impid": "my-imp-id",
+                "price": 12.00,
+                "w": 200,
+                "h": 250,
+                "crid": "creative-1",
+                "cat": [
+                  "IAB1-1"
+                ]
+              }
+            }
+          ]
+        }
+      }
+    },
+    "audienceNetwork": {
+      "mockResponse": {
+        "httpCalls": [
+          {
+            "uri": "audienceNetworkTest.com",
+            "requestbody": "audienceNetworkTestRequestBody",
+            "responsebody": "audienceNetworkTestResponseBody",
+            "status": 200
+          }
+        ]
+      }
+    }
+  },
+  "response": {
+    "bids": {
+      "id": "some-request-id",
+      "seatbid": [
+        {
+          "seat": "appnexus",
+          "bid": [
+            {
+              "id": "winning-bid",
+              "impid": "my-imp-id",
+              "price": 12.00,
+              "w": 200,
+              "h": 250,
+              "crid": "creative-1",
+              "cat": [
+                "IAB1-1"
+              ],
+              "ext": {
+                "prebid": {
+                  "type": "",
+                  "targeting": {
+                    "hb_bidder": "appnexus",
+                    "hb_bidder_appnexus": "appnexus",
+                    "hb_cache_host": "www.pbcserver.com",
+                    "hb_cache_host_appnex": "www.pbcserver.com",
+                    "hb_cache_path": "/pbcache/endpoint",
+                    "hb_cache_path_appnex": "/pbcache/endpoint",
+                    "hb_size": "200x250",
+                    "hb_size_appnexus": "200x250",
+                    "hb_pb": "12.00",
+                    "hb_pb_appnexus": "12.00",
+                    "hb_pb_cat_dur": "12.00_VideoGames_15s",
+                    "hb_pb_cat_dur_appnex": "12.00_VideoGames_15s"
+                  }
+                }
+              }
+            }
+          ]
+        }
+      ]
+    },
+    "ext": {
+      "debug": {
+        "httpcalls": {
+          "appnexus": [
+            {
+              "uri": "appnexusTest.com",
+              "requestbody": "appnexusTestRequestBody",
+              "responsebody": "appnexusTestResponseBody",
+              "status": 200
+            }
+          ],
+          "audienceNetwork": [
+            {
+              "uri": "audienceNetworkTest.com",
+              "requestbody": "audienceNetworkTestRequestBody",
+              "responsebody": "audienceNetworkTestResponseBody",
+              "status": 200
+            }
+          ]
+        },
+        "resolvedrequest": {
+          "id": "some-request-id",
+          "imp": [
+            {
+              "id": "my-imp-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ]
+              },
+              "ext": {
+                "appnexus": {
+                  "placementId": 1
+                },
+                "audienceNetwork": {
+                  "placementId": "some-placement"
+                }
+              }
+            },
+            {
+              "id": "imp-id-2",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ]
+              },
+              "ext": {
+                "appnexus": {
+                  "placementId": 2
+                },
+                "audienceNetwork": {
+                  "placementId": "some-other-placement"
+                }
+              }
+            }
+          ],
+          "site": {
+            "page": "test.somepage.com"
+          },
+          "test": 1,
+          "ext": {
+            "prebid": {
+              "targeting": {
+                "durationRangeSec": [
+                  15,
+                  30
+                ],
+                "includebrandcategory": {
+                  "primaryadserver": 1,
+                  "publisher": "",
+                  "withCategory": true,
+                  "translateCategories": true
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+
diff --git a/exchange/exchangetest/request-multi-bidders-one-no-resp.json b/exchange/exchangetest/request-multi-bidders-one-no-resp.json
new file mode 100644
index 00000000..b7179ccb
--- /dev/null
+++ b/exchange/exchangetest/request-multi-bidders-one-no-resp.json
@@ -0,0 +1,122 @@
+{
+  "incomingRequest": {
+    "ortbRequest": {
+      "id": "some-request-id",
+      "site": {
+        "page": "test.somepage.com"
+      },
+      "imp": [
+        {
+          "id": "my-imp-id",
+          "video": {
+            "mimes": ["video/mp4"]
+          },
+          "ext": {
+            "appnexus": {
+              "placementId": 1
+            },
+            "audienceNetwork": {
+              "placementId": "some-placement"
+            }
+          }
+        },
+        {
+          "id": "imp-id-2",
+          "video": {
+            "mimes": ["video/mp4"]
+          },
+          "ext": {
+            "appnexus": {
+              "placementId": 2
+            },
+            "audienceNetwork": {
+              "placementId": "some-other-placement"
+            }
+          }
+        }
+      ],
+      "ext": {
+        "prebid": {
+          "targeting": {
+            "durationRangeSec": [15,30],
+            "includebrandcategory": {
+              "primaryadserver": 1,
+              "publisher": "",
+              "withCategory": true,
+              "translateCategories": true
+            }
+          }
+        }
+      }
+    }
+  },
+  "outgoingRequests": {
+    "appnexus": {
+      "mockResponse": {
+        "pbsSeatBid": {
+          "pbsBids": [
+            {
+              "ortbBid": {
+                "id": "winning-bid",
+                "impid": "my-imp-id",
+                "price": 12.00,
+                "w": 200,
+                "h": 250,
+                "crid": "creative-1",
+                "cat": [
+                  "IAB1-1"
+                ]
+              }
+            }
+          ]
+        }
+      }
+    },
+    "audienceNetwork": {
+      "mockResponse": {
+
+      }
+    }
+  },
+  "response": {
+    "bids": {
+      "id": "some-request-id",
+      "seatbid": [
+        {
+          "seat": "appnexus",
+          "bid": [
+            {
+            "id": "winning-bid",
+            "impid": "my-imp-id",
+            "price": 12.00,
+            "w": 200,
+            "h": 250,
+            "crid": "creative-1",
+            "cat": ["IAB1-1"],
+            "ext": {
+              "prebid": {
+                "type": "",
+                "targeting": {
+                  "hb_bidder": "appnexus",
+                  "hb_bidder_appnexus": "appnexus",
+                  "hb_cache_host": "www.pbcserver.com",
+                  "hb_cache_host_appnex": "www.pbcserver.com",
+                  "hb_cache_path": "/pbcache/endpoint",
+                  "hb_cache_path_appnex": "/pbcache/endpoint",
+                  "hb_size": "200x250",
+                  "hb_size_appnexus": "200x250",
+                  "hb_pb": "12.00",
+                  "hb_pb_appnexus": "12.00",
+                  "hb_pb_cat_dur": "12.00_VideoGames_15s",
+                  "hb_pb_cat_dur_appnex": "12.00_VideoGames_15s"
+                }
+              }
+            }
+          }]
+        }
+      ]
+    }
+  }
+}
+
+
diff --git a/pbsmetrics/config/metrics_test.go b/pbsmetrics/config/metrics_test.go
index ad817ba7..d2374f95 100644
--- a/pbsmetrics/config/metrics_test.go
+++ b/pbsmetrics/config/metrics_test.go
@@ -115,6 +115,9 @@ func TestMultiMetricsEngine(t *testing.T) {
 	for i := 0; i < 3; i++ {
 		metricsEngine.RecordImps(impTypeLabels)
 	}
+
+	metricsEngine.RecordRequestQueueTime(false, pbsmetrics.ReqTypeVideo, time.Duration(1))
+
 	//Make the metrics engine, instantiated here with goEngine, fill its RequestStatuses[RequestType][pbsmetrics.RequestStatusXX] with the new boolean values added to pbsmetrics.Labels
 	VerifyMetrics(t, "RequestStatuses.OpenRTB2.OK", goEngine.RequestStatuses[pbsmetrics.ReqTypeORTB2Web][pbsmetrics.RequestStatusOK].Count(), 5)
 	VerifyMetrics(t, "RequestStatuses.Legacy.OK", goEngine.RequestStatuses[pbsmetrics.ReqTypeLegacy][pbsmetrics.RequestStatusOK].Count(), 0)
@@ -148,6 +151,9 @@ func TestMultiMetricsEngine(t *testing.T) {
 	}
 	VerifyMetrics(t, "AdapterMetrics.AppNexus.GotBidsMeter", goEngine.AdapterMetrics[openrtb_ext.BidderAppnexus].GotBidsMeter.Count(), 0)
 	VerifyMetrics(t, "AdapterMetrics.AppNexus.NoBidMeter", goEngine.AdapterMetrics[openrtb_ext.BidderAppnexus].NoBidMeter.Count(), 5)
+
+	VerifyMetrics(t, "RecordRequestQueueTime.Video.Rejected", goEngine.RequestsQueueTimer[pbsmetrics.ReqTypeVideo][false].Count(), 1)
+	VerifyMetrics(t, "RecordRequestQueueTime.Video.Accepted", goEngine.RequestsQueueTimer[pbsmetrics.ReqTypeVideo][true].Count(), 0)
 }
 
 func VerifyMetrics(t *testing.T, name string, actual int64, expected int64) {
diff --git a/pbsmetrics/go_metrics_test.go b/pbsmetrics/go_metrics_test.go
index b403733d..253ff69e 100644
--- a/pbsmetrics/go_metrics_test.go
+++ b/pbsmetrics/go_metrics_test.go
@@ -50,6 +50,9 @@ func TestNewMetrics(t *testing.T) {
 	ensureContains(t, registry, "requests.badinput.video", m.RequestStatuses[ReqTypeVideo][RequestStatusBadInput])
 	ensureContains(t, registry, "requests.err.video", m.RequestStatuses[ReqTypeVideo][RequestStatusErr])
 	ensureContains(t, registry, "requests.networkerr.video", m.RequestStatuses[ReqTypeVideo][RequestStatusNetworkErr])
+
+	ensureContains(t, registry, "queued_requests.video.rejected", m.RequestsQueueTimer[ReqTypeVideo][false])
+	ensureContains(t, registry, "queued_requests.video.accepted", m.RequestsQueueTimer[ReqTypeVideo][true])
 }
 
 func TestRecordBidType(t *testing.T) {
diff --git a/pbsmetrics/prometheus/prometheus_test.go b/pbsmetrics/prometheus/prometheus_test.go
index f76480f0..e4d6a4f7 100644
--- a/pbsmetrics/prometheus/prometheus_test.go
+++ b/pbsmetrics/prometheus/prometheus_test.go
@@ -881,6 +881,48 @@ func TestMetricAccumulationSpotCheck(t *testing.T) {
 		expectedValue)
 }
 
+func TestRecordRequestQueueTimeMetric(t *testing.T) {
+	performTest := func(m *Metrics, requestStatus bool, requestType pbsmetrics.RequestType, timeInSec float64) {
+		m.RecordRequestQueueTime(requestStatus, requestType, time.Duration(timeInSec*float64(time.Second)))
+	}
+
+	testCases := []struct {
+		description   string
+		status        string
+		testCase      func(m *Metrics)
+		expectedCount uint64
+		expectedSum   float64
+	}{
+		{
+			description: "Success",
+			status:      requestSuccessLabel,
+			testCase: func(m *Metrics) {
+				performTest(m, true, pbsmetrics.ReqTypeVideo, 2)
+			},
+			expectedCount: 1,
+			expectedSum:   2,
+		},
+		{
+			description: "TimeoutError",
+			status:      requestRejectLabel,
+			testCase: func(m *Metrics) {
+				performTest(m, false, pbsmetrics.ReqTypeVideo, 50)
+			},
+			expectedCount: 1,
+			expectedSum:   50,
+		},
+	}
+
+	m := createMetricsForTesting()
+	for _, test := range testCases {
+
+		test.testCase(m)
+
+		result := getHistogramFromHistogramVecByTwoKeys(m.requestsQueueTimer, requestTypeLabel, "video", requestStatusLabel, test.status)
+		assertHistogram(t, test.description, result, test.expectedCount, test.expectedSum)
+	}
+}
+
 func assertCounterValue(t *testing.T, description, name string, counter prometheus.Counter, expected float64) {
 	m := dto.Metric{}
 	counter.Write(&m)
@@ -906,6 +948,24 @@ func getHistogramFromHistogramVec(histogram *prometheus.HistogramVec, labelKey,
 	return result
 }
 
+func getHistogramFromHistogramVecByTwoKeys(histogram *prometheus.HistogramVec, label1Key, label1Value, label2Key, label2Value string) dto.Histogram {
+	var result dto.Histogram
+	processMetrics(histogram, func(m dto.Metric) {
+		for ind, label := range m.GetLabel() {
+			if label.GetName() == label1Key && label.GetValue() == label1Value {
+				valInd := ind
+				if ind == 1 {
+					valInd = 0
+				}
+				if m.Label[valInd].GetName() == label2Key && m.Label[valInd].GetValue() == label2Value {
+					result = *m.GetHistogram()
+				}
+			}
+		}
+	})
+	return result
+}
+
 func processMetrics(collector prometheus.Collector, handler func(m dto.Metric)) {
 	collectorChan := make(chan prometheus.Metric)
 	go func() {
diff --git a/router/aspects/request_timeout_handler_test.go b/router/aspects/request_timeout_handler_test.go
index 5283d5d5..cdc920c4 100644
--- a/router/aspects/request_timeout_handler_test.go
+++ b/router/aspects/request_timeout_handler_test.go
@@ -1,12 +1,14 @@
 package aspects
 
 import (
+	"github.com/julienschmidt/httprouter"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/pbsmetrics"
 	"net/http"
 	"net/http/httptest"
+	"strconv"
 	"testing"
-
-	"github.com/julienschmidt/httprouter"
-	"github.com/prebid/prebid-server/config"
+	"time"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -23,6 +25,7 @@ func TestAny(t *testing.T) {
 		expectedRespCodeMessage string
 		expectedRespBody        string
 		expectedRespBodyMessage string
+		requestStatusMetrics    bool
 	}{
 		{
 			//TestQueuedRequestTimeoutWithTimeout
@@ -33,6 +36,7 @@ func TestAny(t *testing.T) {
 			expectedRespCodeMessage: "Http response code is incorrect, should be 408",
 			expectedRespBody:        "Queued request processing time exceeded maximum",
 			expectedRespBodyMessage: "Body should have error message",
+			requestStatusMetrics:    false,
 		},
 		{
 			//TestQueuedRequestTimeoutNoTimeout
@@ -43,6 +47,7 @@ func TestAny(t *testing.T) {
 			expectedRespCodeMessage: "Http response code is incorrect, should be 200",
 			expectedRespBody:        "Executed",
 			expectedRespBodyMessage: "Body should be present in response",
+			requestStatusMetrics:    true,
 		},
 		{
 			//TestQueuedRequestNoHeaders
@@ -53,6 +58,7 @@ func TestAny(t *testing.T) {
 			expectedRespCodeMessage: "Http response code is incorrect, should be 200",
 			expectedRespBody:        "Executed",
 			expectedRespBodyMessage: "Body should be present in response",
+			requestStatusMetrics:    true,
 		},
 		{
 			//TestQueuedRequestSomeHeaders
@@ -63,31 +69,13 @@ func TestAny(t *testing.T) {
 			expectedRespCodeMessage: "Http response code is incorrect, should be 200",
 			expectedRespBody:        "Executed",
 			expectedRespBodyMessage: "Body should be present in response",
-		},
-		{
-			//TestQueuedRequestAllHeadersIncorrect
-			reqTimeInQueue:          "test1",
-			reqTimeOut:              "test2",
-			setHeaders:              true,
-			expectedRespCode:        http.StatusInternalServerError,
-			expectedRespCodeMessage: "Http response code is incorrect, should be 400",
-			expectedRespBody:        "Request timeout headers are incorrect (wrong format)",
-			expectedRespBodyMessage: "Body should have error message",
-		},
-		{
-			//TestQueuedRequestSomeHeadersIncorrect
-			reqTimeInQueue:          "test1",
-			reqTimeOut:              "123",
-			setHeaders:              true,
-			expectedRespCode:        http.StatusInternalServerError,
-			expectedRespCodeMessage: "Http response code is incorrect, should be 400",
-			expectedRespBody:        "Request timeout headers are incorrect (wrong format)",
-			expectedRespBodyMessage: "Body should have error message",
+			requestStatusMetrics:    true,
 		},
 	}
 
 	for _, test := range testCases {
-		result := ExecuteAspectRequest(t, test.reqTimeInQueue, test.reqTimeOut, test.setHeaders)
+		reqTimeFloat, _ := strconv.ParseFloat(test.reqTimeInQueue, 64)
+		result := ExecuteAspectRequest(t, test.reqTimeInQueue, test.reqTimeOut, test.setHeaders, pbsmetrics.ReqTypeVideo, test.requestStatusMetrics, reqTimeFloat)
 		assert.Equal(t, test.expectedRespCode, result.Code, test.expectedRespCodeMessage)
 		assert.Equal(t, test.expectedRespBody, string(result.Body.Bytes()), test.expectedRespBodyMessage)
 	}
@@ -101,7 +89,7 @@ func MockHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
 	w.Write([]byte("Executed"))
 }
 
-func ExecuteAspectRequest(t *testing.T, timeInQueue string, reqTimeout string, setHeaders bool) *httptest.ResponseRecorder {
+func ExecuteAspectRequest(t *testing.T, timeInQueue string, reqTimeout string, setHeaders bool, requestType pbsmetrics.RequestType, status bool, requestDuration float64) *httptest.ResponseRecorder {
 	rw := httptest.NewRecorder()
 	req, err := http.NewRequest("POST", "/test", nil)
 	if err != nil {
@@ -114,7 +102,11 @@ func ExecuteAspectRequest(t *testing.T, timeInQueue string, reqTimeout string, s
 
 	customHeaders := config.RequestTimeoutHeaders{reqTimeInQueueHeaderName, reqTimeoutHeaderName}
 
-	handler := QueuedRequestTimeout(MockEndpoint(), customHeaders)
+	metrics := &pbsmetrics.MetricsEngineMock{}
+
+	metrics.On("RecordRequestQueueTime", status, requestType, time.Duration(requestDuration*float64(time.Second))).Once()
+
+	handler := QueuedRequestTimeout(MockEndpoint(), customHeaders, metrics, requestType)
 
 	r := httprouter.New()
 	r.POST("/test", handler)
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
old mode 100644
new mode 100755
index 383e24d8..3e1de8ad
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -44,6 +44,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderMarsmedia):        syncConfig,
 			string(openrtb_ext.BidderMgid):             syncConfig,
 			string(openrtb_ext.BidderNanoInteractive):  syncConfig,
+			string(openrtb_ext.BidderNinthDecimal):     syncConfig,
 			string(openrtb_ext.BidderOpenx):            syncConfig,
 			string(openrtb_ext.BidderPubmatic):         syncConfig,
 			string(openrtb_ext.BidderPulsepoint):       syncConfig,
@@ -56,6 +57,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderSovrn):            syncConfig,
 			string(openrtb_ext.BidderSmartRTB):         syncConfig,
 			string(openrtb_ext.BidderSynacormedia):     syncConfig,
+			string(openrtb_ext.BidderTelaria):          syncConfig,
 			string(openrtb_ext.BidderTriplelift):       syncConfig,
 			string(openrtb_ext.BidderTripleliftNative): syncConfig,
 			string(openrtb_ext.BidderUcfunnel):         syncConfig,
@@ -65,17 +67,19 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderVisx):             syncConfig,
 			string(openrtb_ext.BidderVrtcal):           syncConfig,
 			string(openrtb_ext.BidderYieldmo):          syncConfig,
+			string(openrtb_ext.BidderYieldone):         syncConfig,
 			string(openrtb_ext.BidderZeroClickFraud):   syncConfig,
 		},
 	}
 
 	adaptersWithoutSyncers := map[openrtb_ext.BidderName]bool{
-		openrtb_ext.BidderAdoppler:  true,
-		openrtb_ext.BidderApplogy:   true,
-		openrtb_ext.BidderTappx:     true,
-		openrtb_ext.BidderKubient:   true,
-		openrtb_ext.BidderPubnative: true,
-		openrtb_ext.BidderKidoz:     true,
+		openrtb_ext.BidderAdgeneration: true,
+		openrtb_ext.BidderAdoppler:     true,
+		openrtb_ext.BidderApplogy:      true,
+		openrtb_ext.BidderTappx:        true,
+		openrtb_ext.BidderKubient:      true,
+		openrtb_ext.BidderPubnative:    true,
+		openrtb_ext.BidderKidoz:        true,
 	}
 
 	for bidder, config := range cfg.Adapters {