Repository: prebid/prebid-server
Pull request #1563 (2020-11-03 07:55:56)

Optionally read IFA value and add it the the request url (Adhese)


Patch:
diff --git a/adapters/adhese/adhese.go b/adapters/adhese/adhese.go
index 10aaf6e8..3938b161 100644
--- a/adapters/adhese/adhese.go
+++ b/adapters/adhese/adhese.go
@@ -73,6 +73,13 @@ func extractRefererParameter(request *openrtb.BidRequest) string {
 	return ""
 }
 
+func extractIfaParameter(request *openrtb.BidRequest) string {
+	if request.Device != nil && request.Device.IFA != "" {
+		return "/xz" + url.QueryEscape(request.Device.IFA)
+	}
+	return ""
+}
+
 func (a *AdheseAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 	errs := make([]error, 0, len(request.Imp))
 
@@ -106,12 +113,13 @@ func (a *AdheseAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapt
 		errs = append(errs, WrapReqError("Could not compose url from template and request account val: "+err.Error()))
 		return nil, errs
 	}
-	complete_url := fmt.Sprintf("%s%s%s%s%s",
+	complete_url := fmt.Sprintf("%s%s%s%s%s%s",
 		host,
 		extractSlotParameter(params),
 		extractTargetParameters(params),
 		extractGdprParameter(request),
-		extractRefererParameter(request))
+		extractRefererParameter(request),
+		extractIfaParameter(request))
 
 	return []*adapters.RequestData{{
 		Method: "GET",
diff --git a/adapters/adoppler/adoppler.go b/adapters/adoppler/adoppler.go
index c604bfea..77eedec1 100644
--- a/adapters/adoppler/adoppler.go
+++ b/adapters/adoppler/adoppler.go
@@ -6,13 +6,18 @@ import (
 	"fmt"
 	"net/http"
 	"net/url"
+	"text/template"
 
+	"github.com/golang/glog"
 	"github.com/mxmCherry/openrtb"
 	"github.com/prebid/prebid-server/adapters"
 	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/macros"
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
+const DefaultClient = "app"
+
 var bidHeaders http.Header = map[string][]string{
 	"Accept":            {"application/json"},
 	"Content-Type":      {"application/json;charset=utf-8"},
@@ -28,11 +33,17 @@ type adsImpExt struct {
 }
 
 type AdopplerAdapter struct {
-	endpoint string
+	endpoint *template.Template
 }
 
 func NewAdopplerBidder(endpoint string) *AdopplerAdapter {
-	return &AdopplerAdapter{endpoint}
+	t, err := template.New("endpoint").Parse(endpoint)
+	if err != nil {
+		glog.Fatalf("Unable to parse endpoint url template: %s", err)
+		return nil
+	}
+
+	return &AdopplerAdapter{t}
 }
 
 func (ads *AdopplerAdapter) MakeRequests(
@@ -65,8 +76,13 @@ func (ads *AdopplerAdapter) MakeRequests(
 			continue
 		}
 
-		uri := fmt.Sprintf("%s/processHeaderBid/%s",
-			ads.endpoint, url.PathEscape(ext.AdUnit))
+		uri, err := ads.bidUri(ext)
+		if err != nil {
+			e := fmt.Sprintf("Unable to build bid URI: %s",
+				err.Error())
+			errs = append(errs, &errortypes.BadInput{e})
+			continue
+		}
 		data := &adapters.RequestData{
 			Method:  "POST",
 			Uri:     uri,
@@ -172,6 +188,18 @@ func (ads *AdopplerAdapter) MakeBids(
 	return adsResp, nil
 }
 
+func (ads *AdopplerAdapter) bidUri(ext *openrtb_ext.ExtImpAdoppler) (string, error) {
+	params := macros.EndpointTemplateParams{}
+	params.AdUnit = url.PathEscape(ext.AdUnit)
+	if ext.Client == "" {
+		params.AccountID = DefaultClient
+	} else {
+		params.AccountID = url.PathEscape(ext.Client)
+	}
+
+	return macros.ResolveMacros(*ads.endpoint, params)
+}
+
 func unmarshalExt(ext json.RawMessage) (*openrtb_ext.ExtImpAdoppler, error) {
 	var bext adapters.ExtImpBidder
 	err := json.Unmarshal(ext, &bext)
diff --git a/adapters/nobid/nobid.go b/adapters/nobid/nobid.go
new file mode 100644
index 00000000..05bcf02f
--- /dev/null
+++ b/adapters/nobid/nobid.go
@@ -0,0 +1,122 @@
+package nobid
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// NoBidAdapter - NoBid Adapter definition
+type NoBidAdapter struct {
+	endpoint string
+}
+
+// NewNoBidBidder Initializes the Bidder
+func NewNoBidBidder(endpoint string) *NoBidAdapter {
+	return &NoBidAdapter{
+		endpoint: endpoint,
+	}
+}
+
+// MakeRequests Makes the OpenRTB request payload
+func (a *NoBidAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+
+	if len(request.Imp) == 0 {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("No Imps in Bid Request"),
+		}}
+	}
+
+	data, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+
+	return []*adapters.RequestData{{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    data,
+		Headers: headers,
+	}}, []error{}
+}
+
+// MakeBids makes the bids
+func (a *NoBidAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if response.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	var bidResp openrtb.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	count := getBidCount(bidResp)
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(count)
+
+	var errs []error
+
+	for _, sb := range bidResp.SeatBid {
+		for i := range sb.Bid {
+			bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					Bid:     &sb.Bid[i],
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+	return bidResponse, errs
+}
+
+func getBidCount(bidResponse openrtb.BidResponse) int {
+	c := 0
+	for _, sb := range bidResponse.SeatBid {
+		c = c + len(sb.Bid)
+	}
+	return c
+}
+
+func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType, error) {
+	mediaType := openrtb_ext.BidTypeBanner
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner == nil && imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			}
+			return mediaType, nil
+		}
+	}
+
+	// This shouldnt happen. Lets handle it just incase by returning an error.
+	return "", &errortypes.BadInput{
+		Message: fmt.Sprintf("Failed to find impression \"%s\"", impID),
+	}
+}
diff --git a/adapters/nobid/usersync.go b/adapters/nobid/usersync.go
new file mode 100644
index 00000000..c21413f5
--- /dev/null
+++ b/adapters/nobid/usersync.go
@@ -0,0 +1,12 @@
+package nobid
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewNoBidSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("nobid", 816, temp, adapters.SyncTypeRedirect)
+}
diff --git a/config/config.go b/config/config.go
index c08031c4..6d8fdbc0 100755
--- a/config/config.go
+++ b/config/config.go
@@ -402,7 +402,11 @@ func validateAdapterEndpoint(endpoint string, adapterName string, errs configErr
 		return append(errs, fmt.Errorf("Invalid endpoint template: %s for adapter: %s. %v", endpoint, adapterName, err))
 	}
 	// Resolve macros (if any) in the endpoint URL
-	resolvedEndpoint, err := macros.ResolveMacros(*endpointTemplate, macros.EndpointTemplateParams{Host: dummyHost, PublisherID: dummyPublisherID, AccountID: dummyAccountID})
+	resolvedEndpoint, err := macros.ResolveMacros(*endpointTemplate, macros.EndpointTemplateParams{
+		Host:        dummyHost,
+		PublisherID: dummyPublisherID,
+		AccountID:   dummyAccountID,
+	})
 	if err != nil {
 		return append(errs, fmt.Errorf("Unable to resolve endpoint: %s for adapter: %s. %v", endpoint, adapterName, err))
 	}
@@ -740,6 +744,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMgid, "https://cm.mgid.com/m?cdsp=363893&adu="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmgid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Bmuidn%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNanoInteractive, "https://ad.audiencemanager.de/hbs/cookie_sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dnanointeractive%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNinthDecimal, "https://rtb.ninthdecimal.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dninthdecimal%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderNoBid, "https://ads.servenobid.com/getsync?tek=pbs&ver=1&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dnobid%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderOpenx, "https://rtb.openx.net/sync/prebid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dopenx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPubmatic, "https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&predirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderPulsepoint, "https://bh.contextweb.com/rtset?pid=561205&ev=1&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dpulsepoint%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25VGUID%25%25")
@@ -927,7 +932,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.adman.endpoint", "http://pub.admanmedia.com/?c=o&m=ortb")
 	v.SetDefault("adapters.admixer.endpoint", "http://inv-nets.admixer.net/pbs.aspx")
 	v.SetDefault("adapters.adocean.endpoint", "https://{{.Host}}")
-	v.SetDefault("adapters.adoppler.endpoint", "http://app.trustedmarketplace.io/ads")
+	v.SetDefault("adapters.adoppler.endpoint", "http://{{.AccountID}}.trustedmarketplace.io/ads/processHeaderBid/{{.AdUnit}}")
 	v.SetDefault("adapters.adpone.endpoint", "http://rtb.adpone.com/bid-request?src=prebid_server")
 	v.SetDefault("adapters.adprime.endpoint", "http://delta.adprime.com/?c=o&m=ortb")
 	v.SetDefault("adapters.adtarget.endpoint", "http://ghb.console.adtarget.com.tr/pbs/ortb")
@@ -974,6 +979,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.mobilefuse.endpoint", "http://mfx-us-east.mobilefuse.com/openrtb?pub_id={{.PublisherID}}")
 	v.SetDefault("adapters.nanointeractive.endpoint", "https://ad.audiencemanager.de/hbs")
 	v.SetDefault("adapters.ninthdecimal.endpoint", "http://rtb.ninthdecimal.com/xp/get?pubid={{.PublisherID}}")
+	v.SetDefault("adapters.nobid.endpoint", "https://ads.servenobid.com/ortb_adreq?tek=pbs&ver=1")
 	v.SetDefault("adapters.openx.endpoint", "http://rtb.openx.net/prebid")
 	v.SetDefault("adapters.orbidder.endpoint", "https://orbidder.otto.de/openrtb2")
 	v.SetDefault("adapters.pubmatic.endpoint", "https://hbopenbid.pubmatic.com/translator?source=prebid-server")
diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go
index 72f8fa65..30d8d456 100755
--- a/exchange/adapter_map.go
+++ b/exchange/adapter_map.go
@@ -63,6 +63,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/mobilefuse"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
 	"github.com/prebid/prebid-server/adapters/ninthdecimal"
+	"github.com/prebid/prebid-server/adapters/nobid"
 	"github.com/prebid/prebid-server/adapters/openx"
 	"github.com/prebid/prebid-server/adapters/orbidder"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
@@ -158,6 +159,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderMobileFuse:      mobilefuse.NewMobileFuseBidder(cfg.Adapters[string(openrtb_ext.BidderMobileFuse)].Endpoint),
 		openrtb_ext.BidderNanoInteractive: nanointeractive.NewNanoIneractiveBidder(cfg.Adapters[string(openrtb_ext.BidderNanoInteractive)].Endpoint),
 		openrtb_ext.BidderNinthDecimal:    ninthdecimal.NewNinthDecimalBidder(cfg.Adapters[string(openrtb_ext.BidderNinthDecimal)].Endpoint),
+		openrtb_ext.BidderNoBid:           nobid.NewNoBidBidder(cfg.Adapters[string(openrtb_ext.BidderNoBid)].Endpoint),
 		openrtb_ext.BidderOrbidder:        orbidder.NewOrbidderBidder(cfg.Adapters[string(openrtb_ext.BidderOrbidder)].Endpoint),
 		openrtb_ext.BidderOpenx:           openx.NewOpenxBidder(cfg.Adapters[string(openrtb_ext.BidderOpenx)].Endpoint),
 		openrtb_ext.BidderPubmatic:        pubmatic.NewPubmaticBidder(client, cfg.Adapters[string(openrtb_ext.BidderPubmatic)].Endpoint),
diff --git a/exchange/bidder.go b/exchange/bidder.go
index 5924e39b..a230041d 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -58,12 +58,14 @@ type adaptedBidder interface {
 // pbsOrtbBid.bidTargets does not need to be filled out by the Bidder. It will be set later by the exchange.
 // pbsOrtbBid.bidVideo is optional but should be filled out by the Bidder if bidType is video.
 // pbsOrtbBid.dealPriority is optionally provided by adapters and used internally by the exchange to support deal targeted campaigns.
+// pbsOrtbBid.dealTierSatisfied is set to true by exchange.updateHbPbCatDur if deal tier satisfied otherwise it will be set to false
 type pbsOrtbBid struct {
-	bid          *openrtb.Bid
-	bidType      openrtb_ext.BidType
-	bidTargets   map[string]string
-	bidVideo     *openrtb_ext.ExtBidPrebidVideo
-	dealPriority int
+	bid               *openrtb.Bid
+	bidType           openrtb_ext.BidType
+	bidTargets        map[string]string
+	bidVideo          *openrtb_ext.ExtBidPrebidVideo
+	dealPriority      int
+	dealTierSatisfied bool
 }
 
 // pbsOrtbSeatBid is a SeatBid returned by an adaptedBidder.
diff --git a/exchange/exchange.go b/exchange/exchange.go
index c1acc0d5..2e8fe76f 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -281,6 +281,7 @@ func validateDealTier(dealTier openrtb_ext.DealTier) bool {
 func updateHbPbCatDur(bid *pbsOrtbBid, dealTier openrtb_ext.DealTier, bidCategory map[string]string) {
 	if bid.dealPriority >= dealTier.MinDealTier {
 		prefixTier := fmt.Sprintf("%s%d_", dealTier.Prefix, bid.dealPriority)
+		bid.dealTierSatisfied = true
 
 		if oldCatDur, ok := bidCategory[bid.bid.ID]; ok {
 			oldCatDurSplit := strings.SplitAfterN(oldCatDur, "_", 2)
@@ -773,9 +774,11 @@ func (e *exchange) makeBid(Bids []*pbsOrtbBid, auc *auction, returnCreative bool
 		bidExt := &openrtb_ext.ExtBid{
 			Bidder: thisBid.bid.Ext,
 			Prebid: &openrtb_ext.ExtBidPrebid{
-				Targeting: thisBid.bidTargets,
-				Type:      thisBid.bidType,
-				Video:     thisBid.bidVideo,
+				Targeting:         thisBid.bidTargets,
+				Type:              thisBid.bidType,
+				Video:             thisBid.bidVideo,
+				DealPriority:      thisBid.dealPriority,
+				DealTierSatisfied: thisBid.dealTierSatisfied,
 			},
 		}
 		if cacheInfo, found := e.getBidCacheInfo(thisBid, auc); found {
diff --git a/macros/macros.go b/macros/macros.go
index a9f77ea9..5d6bd7af 100644
--- a/macros/macros.go
+++ b/macros/macros.go
@@ -12,6 +12,7 @@ type EndpointTemplateParams struct {
 	ZoneID      string
 	SourceId    string
 	AccountID   string
+	AdUnit      string
 }
 
 // UserSyncTemplateParams specifies params for an user sync URL template
diff --git a/openrtb_ext/bid.go b/openrtb_ext/bid.go
index 09ee375b..75d83c9d 100644
--- a/openrtb_ext/bid.go
+++ b/openrtb_ext/bid.go
@@ -12,11 +12,15 @@ type ExtBid struct {
 }
 
 // ExtBidPrebid defines the contract for bidresponse.seatbid.bid[i].ext.prebid
+// DealPriority represents priority of deal bid. If its non deal bid then value will be 0
+// DealTierSatisfied true represents corresponding bid has satisfied the deal tier
 type ExtBidPrebid struct {
-	Cache     *ExtBidPrebidCache `json:"cache,omitempty"`
-	Targeting map[string]string  `json:"targeting,omitempty"`
-	Type      BidType            `json:"type"`
-	Video     *ExtBidPrebidVideo `json:"video,omitempty"`
+	Cache             *ExtBidPrebidCache `json:"cache,omitempty"`
+	Targeting         map[string]string  `json:"targeting,omitempty"`
+	Type              BidType            `json:"type"`
+	Video             *ExtBidPrebidVideo `json:"video,omitempty"`
+	DealPriority      int                `json:"dealpriority,omitempty"`
+	DealTierSatisfied bool               `json:"dealtiersatisfied,omitempty"`
 }
 
 // ExtBidPrebidCache defines the contract for  bidresponse.seatbid.bid[i].ext.prebid.cache
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 0493b4da..dd482a2e 100755
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -82,6 +82,7 @@ const (
 	BidderMobileFuse       BidderName = "mobilefuse"
 	BidderNanoInteractive  BidderName = "nanointeractive"
 	BidderNinthDecimal     BidderName = "ninthdecimal"
+	BidderNoBid            BidderName = "nobid"
 	BidderOpenx            BidderName = "openx"
 	BidderOrbidder         BidderName = "orbidder"
 	BidderPubmatic         BidderName = "pubmatic"
@@ -174,6 +175,7 @@ var BidderMap = map[string]BidderName{
 	"mobilefuse":        BidderMobileFuse,
 	"nanointeractive":   BidderNanoInteractive,
 	"ninthdecimal":      BidderNinthDecimal,
+	"nobid":             BidderNoBid,
 	"openx":             BidderOpenx,
 	"orbidder":          BidderOrbidder,
 	"pubmatic":          BidderPubmatic,
diff --git a/openrtb_ext/imp_adoppler.go b/openrtb_ext/imp_adoppler.go
index 4b3ba97c..9d4d5e5c 100644
--- a/openrtb_ext/imp_adoppler.go
+++ b/openrtb_ext/imp_adoppler.go
@@ -1,5 +1,6 @@
 package openrtb_ext
 
 type ExtImpAdoppler struct {
+	Client string `json:"client"`
 	AdUnit string `json:"adunit"`
 }
diff --git a/openrtb_ext/imp_nobid.go b/openrtb_ext/imp_nobid.go
new file mode 100644
index 00000000..8af16952
--- /dev/null
+++ b/openrtb_ext/imp_nobid.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ExtImpNoBid struct {
+	SiteID      string `json:"siteId"`
+	PlacementID string `json:"placementId"`
+}
diff --git a/static/bidder-info/nobid.yaml b/static/bidder-info/nobid.yaml
new file mode 100644
index 00000000..51a55de4
--- /dev/null
+++ b/static/bidder-info/nobid.yaml
@@ -0,0 +1,11 @@
+maintainer:
+  email: "developers@nobid.io"
+capabilities:
+  site:
+    mediaTypes:
+      - banner
+      - video
+  app:
+    mediaTypes:
+      - banner
+      - video
diff --git a/static/bidder-params/adoppler.json b/static/bidder-params/adoppler.json
index c2bdde4f..508eef47 100644
--- a/static/bidder-params/adoppler.json
+++ b/static/bidder-params/adoppler.json
@@ -7,6 +7,10 @@
       "adunit": {
         "type": "string",
         "description": "AdUnit to bid against to."
+      },
+      "client": {
+        "type": "string",
+        "description": "Client name."
       }
   },
   "required": ["adunit"]
diff --git a/static/bidder-params/nobid.json b/static/bidder-params/nobid.json
new file mode 100644
index 00000000..576dbfec
--- /dev/null
+++ b/static/bidder-params/nobid.json
@@ -0,0 +1,18 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "NoBid Adapter Params",
+    "description": "A schema which validates params accepted by the NoBid adapter",
+  
+    "type": "object",
+    "properties": {
+      "siteId": {
+        "type": "integer",
+        "description": "A Required ID which identifies the NoBid site. The siteId paramerter is provided by your NoBid account manager."
+      }, "placementId": { 
+    	  "type": "integer",
+    	  "description": "An oprional ID which identifies an adunit in a site. The placementId paramerter is provided by your NoBid account manager."
+      }
+    },
+    "required": ["siteId"]
+  }
+  
\ No newline at end of file
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
index 4a811aa9..a9d909db 100755
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -50,6 +50,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/mgid"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
 	"github.com/prebid/prebid-server/adapters/ninthdecimal"
+	"github.com/prebid/prebid-server/adapters/nobid"
 	"github.com/prebid/prebid-server/adapters/openx"
 	"github.com/prebid/prebid-server/adapters/pubmatic"
 	"github.com/prebid/prebid-server/adapters/pulsepoint"
@@ -133,6 +134,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderMgid, mgid.NewMgidSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderNanoInteractive, nanointeractive.NewNanoInteractiveSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderNinthDecimal, ninthdecimal.NewNinthDecimalSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderNoBid, nobid.NewNoBidSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderOpenx, openx.NewOpenxSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderPubmatic, pubmatic.NewPubmaticSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderPulsepoint, pulsepoint.NewPulsepointSyncer)


Test patch:
diff --git a/adapters/adhese/adhesetest/exemplary/banner-internal.json b/adapters/adhese/adhesetest/exemplary/banner-internal.json
index 3a31d0cc..50efe4a6 100644
--- a/adapters/adhese/adhesetest/exemplary/banner-internal.json
+++ b/adapters/adhese/adhesetest/exemplary/banner-internal.json
@@ -37,12 +37,15 @@
       "publisher": {
         "id": "123"
       }
+    },
+    "device": {
+      "IFA": "dum-my"
     }
   },
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy"
+        "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy/xzdum-my"
       },
       "mockResponse": {
         "status": 200,
diff --git a/adapters/adoppler/adoppler_test.go b/adapters/adoppler/adoppler_test.go
index e7d908df..646852a1 100644
--- a/adapters/adoppler/adoppler_test.go
+++ b/adapters/adoppler/adoppler_test.go
@@ -7,6 +7,6 @@ import (
 )
 
 func TestJsonSamples(t *testing.T) {
-	bidder := NewAdopplerBidder("http://adoppler.com")
+	bidder := NewAdopplerBidder("http://{{.AccountID}}.trustedmarketplace.com/processHeaderBid/{{.AdUnit}}")
 	adapterstest.RunJSONBidderTest(t, "adopplertest", bidder)
 }
diff --git a/adapters/adoppler/adopplertest/exemplary/custom-client.json b/adapters/adoppler/adopplertest/exemplary/custom-client.json
new file mode 100644
index 00000000..6bb32f71
--- /dev/null
+++ b/adapters/adoppler/adopplertest/exemplary/custom-client.json
@@ -0,0 +1,80 @@
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1",
+            "client":"client1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://client1.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1",
+                  "client":"client1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-unit1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-unit1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>An ad</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+    {
+      "currency":"USD",
+      "bids":[
+        {
+          "bid":{
+            "id":"req1-unit1-bid1",
+            "impid":"imp1",
+            "price":0.12,
+            "adm":"<b>An ad</b>"
+          },
+          "type":"banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/exemplary/default-client.json b/adapters/adoppler/adopplertest/exemplary/default-client.json
new file mode 100644
index 00000000..25fb7197
--- /dev/null
+++ b/adapters/adoppler/adopplertest/exemplary/default-client.json
@@ -0,0 +1,78 @@
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-unit1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-unit1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>An ad</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+    {
+      "currency":"USD",
+      "bids":[
+        {
+          "bid":{
+            "id":"req1-unit1-bid1",
+            "impid":"imp1",
+            "price":0.12,
+            "adm":"<b>An ad</b>"
+          },
+          "type":"banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/exemplary/multibid.json b/adapters/adoppler/adopplertest/exemplary/multibid.json
deleted file mode 100644
index 851f4c5b..00000000
--- a/adapters/adoppler/adopplertest/exemplary/multibid.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}},
-                           {"id": "imp2",
-                            "video": {"minduration": 120,
-                                      "mimes": ["video/mp4"]},
-                            "ext": {"bidder": {"adunit": "unit2"}}},
-                           {"id": "imp3",
-                            "native": {"request": "{}"},
-                            "ext": {"bidder": {"adunit": "unit3"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit2",
-                                    "body": {"id": "req1-unit2",
-                                        "imp": [{"id": "imp2",
-                                                 "video": {"minduration": 120,
-                                                           "mimes": ["video/mp4"]},
-                                                 "ext": {"bidder": {"adunit": "unit2"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp2-resp2",
-                                          "seatbid": [{"bid": [{"id": "req1-imp2-bid1",
-                                                                "impid": "imp2",
-                                                                "price": 0.24,
-                                                                "adm": "<VAST />",
-                                                                "cat": ["IAB1", "IAB2"],
-                                                                "ext": {"ads": {"video": {"duration": 121}}}}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit3",
-                                    "body": {"id": "req1-unit3",
-                                        "imp": [{"id": "imp3",
-                                                 "native": {"request": "{}"},
-                                                 "ext": {"bidder": {"adunit": "unit3"}}}]}},
-                "mockResponse": {"status": 204,
-                                 "body": ""}}],
- "expectedBidResponses": [{"currency": "USD",
-                           "bids": [{"bid": {"id": "req1-imp1-bid1",
-                                             "impid": "imp1",
-                                             "price": 0.12,
-                                             "adm": "<b>a banner</b>"},
-                                     "type": "banner"}]},
-                          {"currency": "USD",
-                           "bids": [{"bid": {"id": "req1-imp2-bid1",
-                                             "impid": "imp2",
-                                             "price": 0.24,
-                                             "adm": "<VAST />",
-                                             "cat": ["IAB1", "IAB2"],
-                                             "ext": {"ads": {"video": {"duration": 121}}}},
-                                     "type": "video"}]}]}
diff --git a/adapters/adoppler/adopplertest/exemplary/multiimp.json b/adapters/adoppler/adopplertest/exemplary/multiimp.json
new file mode 100644
index 00000000..6eebbe43
--- /dev/null
+++ b/adapters/adoppler/adopplertest/exemplary/multiimp.json
@@ -0,0 +1,207 @@
+{
+   "mockBidRequest":{
+      "id":"req1",
+      "imp":[
+         {
+            "id":"imp1",
+            "banner":{
+               "w":100,
+               "h":200
+            },
+            "ext":{
+               "bidder":{
+                  "adunit":"unit1"
+               }
+            }
+         },
+         {
+            "id":"imp2",
+            "video":{
+               "minduration":120,
+               "mimes":[
+                  "video/mp4"
+               ]
+            },
+            "ext":{
+               "bidder":{
+                  "adunit":"unit2"
+               }
+            }
+         },
+         {
+            "id":"imp3",
+            "native":{
+               "request":"{}"
+            },
+            "ext":{
+               "bidder":{
+                  "adunit":"unit3"
+               }
+            }
+         }
+      ]
+   },
+   "httpCalls":[
+      {
+         "expectedRequest":{
+            "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+            "body":{
+               "id":"req1-unit1",
+               "imp":[
+                  {
+                     "id":"imp1",
+                     "banner":{
+                        "w":100,
+                        "h":200
+                     },
+                     "ext":{
+                        "bidder":{
+                           "adunit":"unit1"
+                        }
+                     }
+                  }
+               ]
+            }
+         },
+         "mockResponse":{
+            "status":200,
+            "body":{
+               "id":"req1-imp1-resp1",
+               "seatbid":[
+                  {
+                     "bid":[
+                        {
+                           "id":"req1-imp1-bid1",
+                           "impid":"imp1",
+                           "price":0.12,
+                           "adm":"<b>a banner</b>"
+                        }
+                     ]
+                  }
+               ],
+               "cur":"USD"
+            }
+         }
+      },
+      {
+         "expectedRequest":{
+            "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit2",
+            "body":{
+               "id":"req1-unit2",
+               "imp":[
+                  {
+                     "id":"imp2",
+                     "video":{
+                        "minduration":120,
+                        "mimes":[
+                           "video/mp4"
+                        ]
+                     },
+                     "ext":{
+                        "bidder":{
+                           "adunit":"unit2"
+                        }
+                     }
+                  }
+               ]
+            }
+         },
+         "mockResponse":{
+            "status":200,
+            "body":{
+               "id":"req1-imp2-resp2",
+               "seatbid":[
+                  {
+                     "bid":[
+                        {
+                           "id":"req1-imp2-bid1",
+                           "impid":"imp2",
+                           "price":0.24,
+                           "adm":"<VAST />",
+                           "cat":[
+                              "IAB1",
+                              "IAB2"
+                           ],
+                           "ext":{
+                              "ads":{
+                                 "video":{
+                                    "duration":121
+                                 }
+                              }
+                           }
+                        }
+                     ]
+                  }
+               ],
+               "cur":"USD"
+            }
+         }
+      },
+      {
+         "expectedRequest":{
+            "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit3",
+            "body":{
+               "id":"req1-unit3",
+               "imp":[
+                  {
+                     "id":"imp3",
+                     "native":{
+                        "request":"{}"
+                     },
+                     "ext":{
+                        "bidder":{
+                           "adunit":"unit3"
+                        }
+                     }
+                  }
+               ]
+            }
+         },
+         "mockResponse":{
+            "status":204,
+            "body":""
+         }
+      }
+   ],
+   "expectedBidResponses":[
+      {
+         "currency":"USD",
+         "bids":[
+            {
+               "bid":{
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+               },
+               "type":"banner"
+            }
+         ]
+      },
+      {
+         "currency":"USD",
+         "bids":[
+            {
+               "bid":{
+                  "id":"req1-imp2-bid1",
+                  "impid":"imp2",
+                  "price":0.24,
+                  "adm":"<VAST />",
+                  "cat":[
+                     "IAB1",
+                     "IAB2"
+                  ],
+                  "ext":{
+                     "ads":{
+                        "video":{
+                           "duration":121
+                        }
+                     }
+                  }
+               },
+               "type":"video"
+            }
+         ]
+      }
+   ]
+}
diff --git a/adapters/adoppler/adopplertest/exemplary/no-bid.json b/adapters/adoppler/adopplertest/exemplary/no-bid.json
deleted file mode 100644
index 0e0f1358..00000000
--- a/adapters/adoppler/adopplertest/exemplary/no-bid.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 204,
-                                 "body": ""}}],
- "expectedBidResponses": []}
diff --git a/adapters/adoppler/adopplertest/supplemental/bad-request.json b/adapters/adoppler/adopplertest/supplemental/bad-request.json
index 3bdd5a55..ae515e01 100644
--- a/adapters/adoppler/adopplertest/supplemental/bad-request.json
+++ b/adapters/adoppler/adopplertest/supplemental/bad-request.json
@@ -1,15 +1,56 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 400,
-                                 "body": ""}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "bad request",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":400,
+        "body":""
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"bad request",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json b/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json
index 4382e36c..d6f17a6b 100644
--- a/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json
+++ b/adapters/adoppler/adopplertest/supplemental/duplicate-imp.json
@@ -1,38 +1,128 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}},
-                           {"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit2"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit2",
-                                    "body": {"id": "req1-unit2",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit2"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "duplicate $.imp.id imp1",
-                             "comparison": "literal"},
-                            {"value": "duplicate $.imp.id imp1",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      },
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit2"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    },
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit2",
+        "body":{
+          "id":"req1-unit2",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit2"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"duplicate $.imp.id imp1",
+      "comparison":"literal"
+    },
+    {
+      "value":"duplicate $.imp.id imp1",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/invalid-impid.json b/adapters/adoppler/adopplertest/supplemental/invalid-impid.json
index 2e6ecf4a..b5f062ac 100644
--- a/adapters/adoppler/adopplertest/supplemental/invalid-impid.json
+++ b/adapters/adoppler/adopplertest/supplemental/invalid-impid.json
@@ -1,20 +1,71 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "invalid",
-                                                                "price": 0.12,
-                                                                "adm": "<b>a banner</b>"}]}],
-                                          "cur": "USD"}}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "unknown impid: invalid",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"invalid",
+                  "price":0.12,
+                  "adm":"<b>a banner</b>"
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"unknown impid: invalid",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/invalid-response.json b/adapters/adoppler/adopplertest/supplemental/invalid-response.json
index 72420881..d0a7d2ef 100644
--- a/adapters/adoppler/adopplertest/supplemental/invalid-response.json
+++ b/adapters/adoppler/adopplertest/supplemental/invalid-response.json
@@ -1,15 +1,56 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": "invalid-json"}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "invalid body: json: cannot unmarshal string into Go value of type openrtb.BidResponse",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":"invalid-json"
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"invalid body: json: cannot unmarshal string into Go value of type openrtb.BidResponse",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json b/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json
index d9cb6daa..c08cdca5 100644
--- a/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json
+++ b/adapters/adoppler/adopplertest/supplemental/invalid-video-ext.json
@@ -1,43 +1,145 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "video": {"minduration": 120,
-                                      "mimes": ["video/mp4"]},
-                            "ext": {"bidder": {"adunit": "unit1"}}},
-                          {"id": "imp2",
-                           "video": {"minduration": 120,
-                                     "mimes": ["video/mp4"]},
-                           "ext": {"bidder": {"adunit": "unit2"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "video": {"minduration": 120,
-                                                           "mimes": ["video/mp4"]},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp1-resp1",
-                                          "seatbid": [{"bid": [{"id": "req1-imp1-bid1",
-                                                                "impid": "imp1",
-                                                                "price": 0.24,
-                                                                "adm": "<VAST />",
-                                                                "cat": ["IAB1", "IAB2"],
-                                                                "ext": {}}]}],
-                                          "cur": "USD"}}},
-               {"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit2",
-                                    "body": {"id": "req1-unit2",
-                                        "imp": [{"id": "imp2",
-                                                 "video": {"minduration": 120,
-                                                           "mimes": ["video/mp4"]},
-                                                 "ext": {"bidder": {"adunit": "unit2"}}}]}},
-                "mockResponse": {"status": 200,
-                                 "body": {"id": "req1-imp2-resp2",
-                                          "seatbid": [{"bid": [{"id": "req1-imp2-bid2",
-                                                                "impid": "imp2",
-                                                                "price": 0.24,
-                                                                "adm": "<VAST />",
-                                                                "cat": ["IAB1", "IAB2"],
-                                                                "ext": ""}]}],
-                                          "cur": "USD"}}}],
- "expectedMakeBidsErrors": [{"value": "$.seatbid.bid.ext.ads.video required",
-                             "comparison": "literal"},
-                            {"value": "json: cannot unmarshal string into Go value of type struct { Ads *adoppler.adsImpExt \"json:\\\"ads\\\"\" }",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "video":{
+          "minduration":120,
+          "mimes":[
+            "video/mp4"
+          ]
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      },
+      {
+        "id":"imp2",
+        "video":{
+          "minduration":120,
+          "mimes":[
+            "video/mp4"
+          ]
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit2"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "video":{
+                "minduration":120,
+                "mimes":[
+                  "video/mp4"
+                ]
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp1-resp1",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp1-bid1",
+                  "impid":"imp1",
+                  "price":0.24,
+                  "adm":"<VAST />",
+                  "cat":[
+                    "IAB1",
+                    "IAB2"
+                  ],
+                  "ext":{
+
+                  }
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    },
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit2",
+        "body":{
+          "id":"req1-unit2",
+          "imp":[
+            {
+              "id":"imp2",
+              "video":{
+                "minduration":120,
+                "mimes":[
+                  "video/mp4"
+                ]
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit2"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":200,
+        "body":{
+          "id":"req1-imp2-resp2",
+          "seatbid":[
+            {
+              "bid":[
+                {
+                  "id":"req1-imp2-bid2",
+                  "impid":"imp2",
+                  "price":0.24,
+                  "adm":"<VAST />",
+                  "cat":[
+                    "IAB1",
+                    "IAB2"
+                  ],
+                  "ext":""
+                }
+              ]
+            }
+          ],
+          "cur":"USD"
+        }
+      }
+    }
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"$.seatbid.bid.ext.ads.video required",
+      "comparison":"literal"
+    },
+    {
+      "value":"json: cannot unmarshal string into Go value of type struct { Ads *adoppler.adsImpExt \"json:\\\"ads\\\"\" }",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/missing-adunit.json b/adapters/adoppler/adopplertest/supplemental/missing-adunit.json
index 82a6a95e..df9bbe57 100644
--- a/adapters/adoppler/adopplertest/supplemental/missing-adunit.json
+++ b/adapters/adoppler/adopplertest/supplemental/missing-adunit.json
@@ -1,9 +1,31 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {}}}]},
- "httpCalls": [],
- "expectedBidResponses": [],
- "expectedMakeRequestsErrors": [{"value": "$.imp.ext.adoppler.adunit required",
-                                 "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeRequestsErrors":[
+    {
+      "value":"$.imp.ext.adoppler.adunit required",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/no-bid.json b/adapters/adoppler/adopplertest/supplemental/no-bid.json
new file mode 100644
index 00000000..08a29481
--- /dev/null
+++ b/adapters/adoppler/adopplertest/supplemental/no-bid.json
@@ -0,0 +1,50 @@
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":204,
+        "body":""
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ]
+}
diff --git a/adapters/adoppler/adopplertest/supplemental/server-error.json b/adapters/adoppler/adopplertest/supplemental/server-error.json
index df23bac0..604b83e7 100644
--- a/adapters/adoppler/adopplertest/supplemental/server-error.json
+++ b/adapters/adoppler/adopplertest/supplemental/server-error.json
@@ -1,15 +1,56 @@
-{"mockBidRequest": {"id": "req1",
-                    "imp":[{"id": "imp1",
-                            "banner": {"w": 100,
-                                       "h": 200},
-                            "ext": {"bidder": {"adunit": "unit1"}}}]},
- "httpCalls": [{"expectedRequest": {"uri": "http://adoppler.com/processHeaderBid/unit1",
-                                    "body": {"id": "req1-unit1",
-                                        "imp": [{"id": "imp1",
-                                                 "banner": {"w": 100, "h": 200},
-                                                 "ext": {"bidder": {"adunit": "unit1"}}}]}},
-                "mockResponse": {"status": 500,
-                                 "body": ""}}],
- "expectedBidResponses": [],
- "expectedMakeBidsErrors": [{"value": "unexpected status: 500",
-                             "comparison": "literal"}]}
+{
+  "mockBidRequest":{
+    "id":"req1",
+    "imp":[
+      {
+        "id":"imp1",
+        "banner":{
+          "w":100,
+          "h":200
+        },
+        "ext":{
+          "bidder":{
+            "adunit":"unit1"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls":[
+    {
+      "expectedRequest":{
+        "uri":"http://app.trustedmarketplace.com/processHeaderBid/unit1",
+        "body":{
+          "id":"req1-unit1",
+          "imp":[
+            {
+              "id":"imp1",
+              "banner":{
+                "w":100,
+                "h":200
+              },
+              "ext":{
+                "bidder":{
+                  "adunit":"unit1"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse":{
+        "status":500,
+        "body":""
+      }
+    }
+  ],
+  "expectedBidResponses":[
+
+  ],
+  "expectedMakeBidsErrors":[
+    {
+      "value":"unexpected status: 500",
+      "comparison":"literal"
+    }
+  ]
+}
diff --git a/adapters/nobid/nobid_test.go b/adapters/nobid/nobid_test.go
new file mode 100644
index 00000000..cb0e8e71
--- /dev/null
+++ b/adapters/nobid/nobid_test.go
@@ -0,0 +1,12 @@
+package nobid
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+func TestJsonSamples(t *testing.T) {
+	nobidAdapter := NewNoBidBidder("http://ads.servenobid.com/ortb_adreq?tek=pbs")
+	adapterstest.RunJSONBidderTest(t, "nobidtest", nobidAdapter)
+}
diff --git a/adapters/nobid/nobidtest/exemplary/banner.json b/adapters/nobid/nobidtest/exemplary/banner.json
new file mode 100644
index 00000000..914eaf24
--- /dev/null
+++ b/adapters/nobid/nobidtest/exemplary/banner.json
@@ -0,0 +1,84 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "banner": {
+            "format": [{"w": 728, "h": 90}]
+          },
+          "ext": {
+            "nobid": {
+              "siteId": "21863532377"
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "id":"test-imp-id",
+                "banner": {
+                  "format": [{"w": 728, "h": 90}]
+                },
+                "ext": {
+                  "nobid": {
+                    "siteId": "21863532377"
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "test-request-id",
+            "seatbid": [
+              {
+                "seat": "ttx",
+                "bid": [{
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "test-imp-id",
+                  "price": 0.500000,
+                  "adm": "some-test-ad",
+                  "crid": "crid_10",
+                  "h": 90,
+                  "w": 728
+                }]
+              }
+            ],
+            "cur": "USD"
+          }
+        }
+      }
+    ],
+  
+    "expectedBidResponses": [
+      {
+        "currency": "USD",
+        "bids": [
+          {
+            "bid": {
+              "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+              "impid": "test-imp-id",
+              "price": 0.5,
+              "adm": "some-test-ad",
+              "crid": "crid_10",
+              "w": 728,
+              "h": 90
+            },
+            "type": "banner"
+          }
+        ]
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/bad-mediatype.json b/adapters/nobid/nobidtest/supplemental/bad-mediatype.json
new file mode 100644
index 00000000..6b07d597
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/bad-mediatype.json
@@ -0,0 +1,47 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "Xbanner": {
+            "format": [{"w": 728, "h": 90}]
+          },
+          "ext": {
+            "nobid": {
+              "siteId": "21863532377"
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "id":"test-imp-id",
+                "ext": {
+                  "nobid": {
+                    "siteId": "21863532377"
+                  }
+                }
+              }
+            ]
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+      {
+      "value": "Unexpected status code: 0. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/bad-request.json b/adapters/nobid/nobidtest/supplemental/bad-request.json
new file mode 100644
index 00000000..00d0f404
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/bad-request.json
@@ -0,0 +1,51 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+          {
+            "id": "test-imp-id",
+            "banner": {
+              "format": [{"w": 728, "h": 90}]
+            },
+            "ext": {
+              "nobid": {
+                "siteId": "000"
+              }
+            }
+          }
+        ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+            "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+            "body": {
+              "id": "test-request-id",
+              "imp": [
+                {
+                  "id":"test-imp-id",
+                  "banner": {
+                    "format": [{"w": 728, "h": 90}]
+                  },
+                  "ext": {
+                    "nobid": {
+                      "siteId": "000"
+                    }
+                  }
+                }
+              ]
+            }
+        },
+        "mockResponse": {
+          "status": 400
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+            "comparison": "literal"
+        }
+    ]
+  }
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/bad-response.json b/adapters/nobid/nobidtest/supplemental/bad-response.json
new file mode 100644
index 00000000..05b6e623
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/bad-response.json
@@ -0,0 +1,71 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "banner": {
+            "format": [{"w": 728, "h": 90}]
+          },
+          "ext": {
+            "nobid": {
+              "siteId": "21863532377"
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+          "body": {
+            "id": "test-request-id",
+            "imp": [
+              {
+                "id":"test-imp-id",
+                "banner": {
+                  "format": [{"w": 728, "h": 90}]
+                },
+                "ext": {
+                  "nobid": {
+                    "siteId": "21863532377"
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "XX",
+            "seatbid": [
+              {
+                "seat": "ttx",
+                "bid": [{
+                  "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                  "impid": "XYZ",
+                  "price": 0.500000,
+                  "adm": "some-test-ad",
+                  "crid": "crid_10",
+                  "h": 90,
+                  "w": 728
+                }]
+              }
+            ],
+            "cur": "USD"
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+      {
+      "value": "Failed to find impression \"XYZ\"",
+      "comparison": "literal"
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/missing-imps.json b/adapters/nobid/nobidtest/supplemental/missing-imps.json
new file mode 100644
index 00000000..93775160
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/missing-imps.json
@@ -0,0 +1,14 @@
+{
+    "expectedMakeRequestsErrors": [
+        {
+          "value": "No Imps in Bid Request",
+          "comparison": "literal"
+        }
+    ],
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": []
+    },
+    "httpCalls": []
+  }
+  
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/no-content.json b/adapters/nobid/nobidtest/supplemental/no-content.json
new file mode 100644
index 00000000..a81ca5bd
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/no-content.json
@@ -0,0 +1,46 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+          {
+            "id": "test-imp-id",
+            "banner": {
+              "format": [{"w": 728, "h": 90}]
+            },
+            "ext": {
+              "nobid": {
+                "siteId": "000"
+              }
+            }
+          }
+        ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+            "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+            "body": {
+              "id": "test-request-id",
+              "imp": [
+                {
+                  "id":"test-imp-id",
+                  "banner": {
+                    "format": [{"w": 728, "h": 90}]
+                  },
+                  "ext": {
+                    "nobid": {
+                      "siteId": "000"
+                    }
+                  }
+                }
+              ]
+            }
+        },
+        "mockResponse": {
+          "status": 204
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": []
+  }
\ No newline at end of file
diff --git a/adapters/nobid/nobidtest/supplemental/notok-response.json b/adapters/nobid/nobidtest/supplemental/notok-response.json
new file mode 100644
index 00000000..ea9d380d
--- /dev/null
+++ b/adapters/nobid/nobidtest/supplemental/notok-response.json
@@ -0,0 +1,51 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+          {
+            "id": "test-imp-id",
+            "banner": {
+              "format": [{"w": 728, "h": 90}]
+            },
+            "ext": {
+              "nobid": {
+                "siteId": "000"
+              }
+            }
+          }
+        ]
+    },
+    "httpCalls": [
+      {
+        "expectedRequest": {
+            "uri": "http://ads.servenobid.com/ortb_adreq?tek=pbs",
+            "body": {
+              "id": "test-request-id",
+              "imp": [
+                {
+                  "id":"test-imp-id",
+                  "banner": {
+                    "format": [{"w": 728, "h": 90}]
+                  },
+                  "ext": {
+                    "nobid": {
+                      "siteId": "000"
+                    }
+                  }
+                }
+              ]
+            }
+        },
+        "mockResponse": {
+          "status": 500
+        }
+      }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Unexpected status code: 500. Run with request.debug = 1 for more info",
+            "comparison": "literal"
+        }
+    ]
+  }
\ No newline at end of file
diff --git a/adapters/nobid/params_test.go b/adapters/nobid/params_test.go
new file mode 100644
index 00000000..75d69943
--- /dev/null
+++ b/adapters/nobid/params_test.go
@@ -0,0 +1,53 @@
+package nobid
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderNoBid, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected nobid params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderNoBid, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"siteId": 25251, "bidfloor": 0.01}`,
+}
+
+var invalidParams = []string{
+	`null`,
+	`nil`,
+	``,
+	`[]`,
+	`true`,
+	`{}`,
+	`{"tagid":12345678}`,
+	`{"tagId":"12345678"}`,
+	`{"tagid":"25251", "bidfloor": 0.01}`,
+	`{"tagId": 12345678}`,
+	`{"placementId": "1"}`,
+	`{"placementId": 1}`,
+}
diff --git a/adapters/nobid/usersync_test.go b/adapters/nobid/usersync_test.go
new file mode 100644
index 00000000..bc55d130
--- /dev/null
+++ b/adapters/nobid/usersync_test.go
@@ -0,0 +1,34 @@
+package nobid
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/ccpa"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNoBidSyncer(t *testing.T) {
+	syncURL := "https://ads.servenobid.com/sync?tek=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect=localhost%2Fsetuid%3Fbidder%3Dtest_bidder%26uid%3D%24UID"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewNoBidSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "1",
+			Consent: "BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA",
+		},
+		CCPA: ccpa.Policy{
+			Consent: "1NYN",
+		},
+	})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "https://ads.servenobid.com/sync?tek=pbs&gdpr=1&gdpr_consent=BOPVK28OVJoTBABABAENBs-AAAAhuAKAANAAoACwAGgAPAAxAB0AHgAQAAiABOADkA&us_privacy=1NYN&redirect=localhost%2Fsetuid%3Fbidder%3Dtest_bidder%26uid%3D%24UID", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index 33411c87..66a3bd67 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -1351,7 +1351,7 @@ func (m *mockExchangeVideo) HoldAuction(ctx context.Context, bidRequest *openrtb
 	if debugLog != nil && debugLog.Enabled {
 		m.cache.called = true
 	}
-	ext := []byte(`{"prebid":{"targeting":{"hb_bidder_appnexus":"appnexus","hb_pb_appnexus":"20.00","hb_pb_cat_dur_appnex":"20.00_395_30s","hb_size":"1x1", "hb_uuid_appnexus":"837ea3b7-5598-4958-8c45-8e9ef2bf7cc1"},"type":"video"},"bidder":{"appnexus":{"brand_id":1,"auction_id":7840037870526938650,"bidder_id":2,"bid_ad_type":1,"creative_info":{"video":{"duration":30,"mimes":["video\/mp4"]}}}}}`)
+	ext := []byte(`{"prebid":{"targeting":{"hb_bidder_appnexus":"appnexus","hb_pb_appnexus":"20.00","hb_pb_cat_dur_appnex":"20.00_395_30s","hb_size":"1x1", "hb_uuid_appnexus":"837ea3b7-5598-4958-8c45-8e9ef2bf7cc1"},"type":"video","dealpriority":0,"dealtiersatisfied":false},"bidder":{"appnexus":{"brand_id":1,"auction_id":7840037870526938650,"bidder_id":2,"bid_ad_type":1,"creative_info":{"video":{"duration":30,"mimes":["video\/mp4"]}}}}}`)
 	return &openrtb.BidResponse{
 		SeatBid: []openrtb.SeatBid{{
 			Seat: "appnexus",
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 09d1af91..ae8bc3c8 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -695,6 +695,11 @@ func TestBidReturnsCreative(t *testing.T) {
 
 		assert.Equal(t, 0, len(resultingErrs), "%s. Test should not return errors \n", test.description)
 		assert.Equal(t, test.expectedCreativeMarkup, resultingBids[0].AdM, "%s. Ad markup string doesn't match expected \n", test.description)
+
+		var bidExt openrtb_ext.ExtBid
+		json.Unmarshal(resultingBids[0].Ext, &bidExt)
+		assert.Equal(t, 0, bidExt.Prebid.DealPriority, "%s. Test should have DealPriority set to 0", test.description)
+		assert.Equal(t, false, bidExt.Prebid.DealTierSatisfied, "%s. Test should have DealTierSatisfied set to false", test.description)
 	}
 }
 
@@ -1514,10 +1519,10 @@ func TestCategoryMapping(t *testing.T) {
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 40.0000, Cat: cats4, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1569,10 +1574,10 @@ func TestCategoryMappingNoIncludeBrandCategory(t *testing.T) {
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 40.0000, Cat: cats4, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "AdapterOverride"}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1623,9 +1628,9 @@ func TestCategoryMappingTranslateCategoriesNil(t *testing.T) {
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 20.0000, Cat: cats2, W: 1, H: 1}
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1705,9 +1710,9 @@ func TestCategoryMappingTranslateCategoriesFalse(t *testing.T) {
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 20.0000, Cat: cats2, W: 1, H: 1}
 	bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids := []*pbsOrtbBid{
 		&bid1_1,
@@ -1757,11 +1762,11 @@ func TestCategoryDedupe(t *testing.T) {
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 20.0000, Cat: cats4, W: 1, H: 1}
 	bid5 := openrtb.Bid{ID: "bid_id5", ImpID: "imp_id5", Price: 20.0000, Cat: cats1, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 50}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	selectedBids := make(map[string]int)
 	expectedCategories := map[string]string{
@@ -1836,11 +1841,11 @@ func TestNoCategoryDedupe(t *testing.T) {
 	bid4 := openrtb.Bid{ID: "bid_id4", ImpID: "imp_id4", Price: 20.0000, Cat: cats4, W: 1, H: 1}
 	bid5 := openrtb.Bid{ID: "bid_id5", ImpID: "imp_id5", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_4 := pbsOrtbBid{&bid4, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_5 := pbsOrtbBid{&bid5, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	selectedBids := make(map[string]int)
 	expectedCategories := map[string]string{
@@ -1916,8 +1921,8 @@ func TestCategoryMappingBidderName(t *testing.T) {
 	bid1 := openrtb.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 10.0000, Cat: cats2, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids1 := []*pbsOrtbBid{
 		&bid1_1,
@@ -1970,8 +1975,8 @@ func TestCategoryMappingBidderNameNoCategories(t *testing.T) {
 	bid1 := openrtb.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 	bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 12.0000, Cat: cats2, W: 1, H: 1}
 
-	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBids1 := []*pbsOrtbBid{
 		&bid1_1,
@@ -2082,7 +2087,7 @@ func TestBidRejectionErrors(t *testing.T) {
 		innerBids := []*pbsOrtbBid{}
 		for _, bid := range test.bids {
 			currentBid := pbsOrtbBid{
-				bid, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: test.duration}, 0,
+				bid, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: test.duration}, 0, false,
 			}
 			innerBids = append(innerBids, &currentBid)
 		}
@@ -2131,8 +2136,8 @@ func TestCategoryMappingTwoBiddersOneBidEachNoCategorySamePrice(t *testing.T) {
 	bidApn1 := openrtb.Bid{ID: "bid_idApn1", ImpID: "imp_idApn1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
 	bidApn2 := openrtb.Bid{ID: "bid_idApn2", ImpID: "imp_idApn2", Price: 10.0000, Cat: cats2, W: 1, H: 1}
 
-	bid1_Apn1 := pbsOrtbBid{&bidApn1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
-	bid1_Apn2 := pbsOrtbBid{&bidApn2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0}
+	bid1_Apn1 := pbsOrtbBid{&bidApn1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
+	bid1_Apn2 := pbsOrtbBid{&bidApn2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}, 0, false}
 
 	innerBidsApn1 := []*pbsOrtbBid{
 		&bid1_Apn1,
@@ -2193,12 +2198,13 @@ func TestUpdateRejections(t *testing.T) {
 
 func TestApplyDealSupport(t *testing.T) {
 	testCases := []struct {
-		description        string
-		dealPriority       int
-		impExt             json.RawMessage
-		targ               map[string]string
-		expectedHbPbCatDur string
-		expectedDealErr    string
+		description               string
+		dealPriority              int
+		impExt                    json.RawMessage
+		targ                      map[string]string
+		expectedHbPbCatDur        string
+		expectedDealErr           string
+		expectedDealTierSatisfied bool
 	}{
 		{
 			description:  "hb_pb_cat_dur should be modified",
@@ -2207,8 +2213,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_movies_30s",
 			},
-			expectedHbPbCatDur: "tier5_movies_30s",
-			expectedDealErr:    "",
+			expectedHbPbCatDur:        "tier5_movies_30s",
+			expectedDealErr:           "",
+			expectedDealTierSatisfied: true,
 		},
 		{
 			description:  "hb_pb_cat_dur should not be modified due to priority not exceeding min",
@@ -2217,8 +2224,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_medicine_30s",
 			},
-			expectedHbPbCatDur: "12.00_medicine_30s",
-			expectedDealErr:    "",
+			expectedHbPbCatDur:        "12.00_medicine_30s",
+			expectedDealErr:           "",
+			expectedDealTierSatisfied: false,
 		},
 		{
 			description:  "hb_pb_cat_dur should not be modified due to invalid config",
@@ -2227,8 +2235,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_games_30s",
 			},
-			expectedHbPbCatDur: "12.00_games_30s",
-			expectedDealErr:    "dealTier configuration invalid for bidder 'appnexus', imp ID 'imp_id1'",
+			expectedHbPbCatDur:        "12.00_games_30s",
+			expectedDealErr:           "dealTier configuration invalid for bidder 'appnexus', imp ID 'imp_id1'",
+			expectedDealTierSatisfied: false,
 		},
 		{
 			description:  "hb_pb_cat_dur should not be modified due to deal priority of 0",
@@ -2237,8 +2246,9 @@ func TestApplyDealSupport(t *testing.T) {
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_auto_30s",
 			},
-			expectedHbPbCatDur: "12.00_auto_30s",
-			expectedDealErr:    "",
+			expectedHbPbCatDur:        "12.00_auto_30s",
+			expectedDealErr:           "",
+			expectedDealTierSatisfied: false,
 		},
 	}
 
@@ -2254,7 +2264,7 @@ func TestApplyDealSupport(t *testing.T) {
 			},
 		}
 
-		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority, false}
 		bidCategory := map[string]string{
 			bid.bid.ID: test.targ["hb_pb_cat_dur"],
 		}
@@ -2270,6 +2280,7 @@ func TestApplyDealSupport(t *testing.T) {
 		dealErrs := applyDealSupport(bidRequest, auc, bidCategory)
 
 		assert.Equal(t, test.expectedHbPbCatDur, bidCategory[auc.winningBidsByBidder["imp_id1"][bidderName].bid.ID], test.description)
+		assert.Equal(t, test.expectedDealTierSatisfied, auc.winningBidsByBidder["imp_id1"][bidderName].dealTierSatisfied, "expectedDealTierSatisfied=%v when %v", test.expectedDealTierSatisfied, test.description)
 		if len(test.expectedDealErr) > 0 {
 			assert.Containsf(t, dealErrs, errors.New(test.expectedDealErr), "Expected error message not found in deal errors")
 		}
@@ -2368,11 +2379,12 @@ func TestValidateDealTier(t *testing.T) {
 
 func TestUpdateHbPbCatDur(t *testing.T) {
 	testCases := []struct {
-		description        string
-		targ               map[string]string
-		dealTier           openrtb_ext.DealTier
-		dealPriority       int
-		expectedHbPbCatDur string
+		description               string
+		targ                      map[string]string
+		dealTier                  openrtb_ext.DealTier
+		dealPriority              int
+		expectedHbPbCatDur        string
+		expectedDealTierSatisfied bool
 	}{
 		{
 			description: "hb_pb_cat_dur should be updated with prefix and tier",
@@ -2384,8 +2396,9 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 				Prefix:      "tier",
 				MinDealTier: 5,
 			},
-			dealPriority:       5,
-			expectedHbPbCatDur: "tier5_movies_30s",
+			dealPriority:              5,
+			expectedHbPbCatDur:        "tier5_movies_30s",
+			expectedDealTierSatisfied: true,
 		},
 		{
 			description: "hb_pb_cat_dur should not be updated due to bid priority",
@@ -2397,8 +2410,9 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 				Prefix:      "tier",
 				MinDealTier: 10,
 			},
-			dealPriority:       6,
-			expectedHbPbCatDur: "12.00_auto_30s",
+			dealPriority:              6,
+			expectedHbPbCatDur:        "12.00_auto_30s",
+			expectedDealTierSatisfied: false,
 		},
 		{
 			description: "hb_pb_cat_dur should be updated with prefix and tier",
@@ -2410,13 +2424,14 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 				Prefix:      "tier",
 				MinDealTier: 1,
 			},
-			dealPriority:       7,
-			expectedHbPbCatDur: "tier7_medicine_30s",
+			dealPriority:              7,
+			expectedHbPbCatDur:        "tier7_medicine_30s",
+			expectedDealTierSatisfied: true,
 		},
 	}
 
 	for _, test := range testCases {
-		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority}
+		bid := pbsOrtbBid{&openrtb.Bid{ID: "123456"}, "video", map[string]string{}, &openrtb_ext.ExtBidPrebidVideo{}, test.dealPriority, false}
 		bidCategory := map[string]string{
 			bid.bid.ID: test.targ["hb_pb_cat_dur"],
 		}
@@ -2424,6 +2439,7 @@ func TestUpdateHbPbCatDur(t *testing.T) {
 		updateHbPbCatDur(&bid, test.dealTier, bidCategory)
 
 		assert.Equal(t, test.expectedHbPbCatDur, bidCategory[bid.bid.ID], test.description)
+		assert.Equal(t, test.expectedDealTierSatisfied, bid.dealTierSatisfied, test.description)
 	}
 }
 
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index 15e6ba19..8ae8581a 100755
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -59,6 +59,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderMgid):             syncConfig,
 			string(openrtb_ext.BidderNanoInteractive):  syncConfig,
 			string(openrtb_ext.BidderNinthDecimal):     syncConfig,
+			string(openrtb_ext.BidderNoBid):            syncConfig,
 			string(openrtb_ext.BidderOpenx):            syncConfig,
 			string(openrtb_ext.BidderPubmatic):         syncConfig,
 			string(openrtb_ext.BidderPulsepoint):       syncConfig,