Repository: prebid/prebid-server
Pull request #2007 (2021-09-22 16:23:59)

Remove Dummy Terminology From Core Code
Replaces the term "Dummy" with the more appropriate and professional "Nil" or "Test" in PBS-Core code. Except for the legacy cache, as that is tied to a host configuration variable and will be removed in the near future anyway.


Patch:
diff --git a/adapters/rubicon/rubicon.go b/adapters/rubicon/rubicon.go
index 1878c41f..80c62df1 100644
--- a/adapters/rubicon/rubicon.go
+++ b/adapters/rubicon/rubicon.go
@@ -5,6 +5,7 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"github.com/buger/jsonparser"
 	"io/ioutil"
 	"net/http"
 	"net/url"
@@ -30,7 +31,6 @@ type RubiconAdapter struct {
 	XAPIPassword string
 }
 
-// used for cookies and such
 func (a *RubiconAdapter) Name() string {
 	return "rubicon"
 }
@@ -73,16 +73,17 @@ type rubiconImpExtRPTrack struct {
 	MintVersion string `json:"mint_version"`
 }
 
+type rubiconImpExt struct {
+	RP   rubiconImpExtRP `json:"rp,omitempty"`
+	GPID string          `json:"gpid,omitempty"`
+}
+
 type rubiconImpExtRP struct {
 	ZoneID int                  `json:"zone_id"`
 	Target json.RawMessage      `json:"target,omitempty"`
 	Track  rubiconImpExtRPTrack `json:"track"`
 }
 
-type rubiconImpExt struct {
-	RP rubiconImpExtRP `json:"rp"`
-}
-
 type rubiconUserExtRP struct {
 	Target json.RawMessage `json:"target,omitempty"`
 }
@@ -102,6 +103,7 @@ type rubiconUserExt struct {
 	TpID        []rubiconExtUserTpID     `json:"tpid,omitempty"`
 	RP          rubiconUserExtRP         `json:"rp"`
 	LiverampIdl string                   `json:"liveramp_idl,omitempty"`
+	Data        json.RawMessage          `json:"data,omitempty"`
 }
 
 type rubiconSiteExtRP struct {
@@ -131,18 +133,6 @@ type rubiconBannerExt struct {
 	RP rubiconBannerExtRP `json:"rp"`
 }
 
-type ExtImpContextData struct {
-	AdSlot string `json:"adslot,omitempty"`
-}
-
-type ExtImpContext struct {
-	Data ExtImpContextData `json:"data,omitempty"`
-}
-
-type ExtImpWithContext struct {
-	Context ExtImpContext `json:"context,omitempty"` // First Party Data context
-}
-
 // ***** Video Extension *****
 type rubiconVideoParams struct {
 	Language     string `json:"language,omitempty"`
@@ -701,11 +691,10 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 	requestImpCopy := request.Imp
 
 	rubiconRequest := *request
-	for i := 0; i < numRequests; i++ {
-		thisImp := requestImpCopy[i]
+	for _, imp := range requestImpCopy {
 
 		var bidderExt adapters.ExtImpBidder
-		if err = json.Unmarshal(thisImp.Ext, &bidderExt); err != nil {
+		if err = json.Unmarshal(imp.Ext, &bidderExt); err != nil {
 			errs = append(errs, &errortypes.BadInput{
 				Message: err.Error(),
 			})
@@ -720,36 +709,15 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 			continue
 		}
 
-		target := rubiconExt.Inventory
-		if rubiconExt.Inventory != nil {
-			rubiconExtInventory := make(map[string]interface{})
-			if err := json.Unmarshal(rubiconExt.Inventory, &rubiconExtInventory); err != nil {
-				errs = append(errs, &errortypes.BadInput{
-					Message: err.Error(),
-				})
-				continue
-			}
-
-			var extImpWithContext ExtImpWithContext
-			if err := json.Unmarshal(thisImp.Ext, &extImpWithContext); err != nil {
-				errs = append(errs, &errortypes.BadInput{
-					Message: err.Error(),
-				})
-				continue
-			}
-
-			// Copy imp[].ext.context.data.adslot is copied to imp[].ext.rp.target.dfp_ad_unit_code,
-			// but with any leading slash dropped
-			adSlot := extImpWithContext.Context.Data.AdSlot
-			if adSlot != "" {
-				rubiconExtInventory["dfp_ad_unit_code"] = strings.TrimLeft(adSlot, "/")
-
-				target, err = json.Marshal(&rubiconExtInventory)
-				if err != nil {
-					errs = append(errs, err)
-					continue
-				}
-			}
+		target, err := updateImpRpTargetWithFpdAttributes(rubiconExt, imp, request.Site, request.App)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+		adSlot, err := getAdSlot(imp)
+		if err != nil {
+			errs = append(errs, err)
+			continue
 		}
 
 		impExt := rubiconImpExt{
@@ -758,35 +726,36 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 				Target: target,
 				Track:  rubiconImpExtRPTrack{Mint: "", MintVersion: ""},
 			},
+			GPID: adSlot,
 		}
-		thisImp.Ext, err = json.Marshal(&impExt)
+		imp.Ext, err = json.Marshal(&impExt)
 		if err != nil {
 			errs = append(errs, err)
 			continue
 		}
 
-		resolvedBidFloor, err := resolveBidFloor(thisImp.BidFloor, thisImp.BidFloorCur, reqInfo)
+		resolvedBidFloor, err := resolveBidFloor(imp.BidFloor, imp.BidFloorCur, reqInfo)
 		if err != nil {
 			errs = append(errs, &errortypes.BadInput{
 				Message: fmt.Sprintf("Unable to convert provided bid floor currency from %s to USD",
-					thisImp.BidFloorCur),
+					imp.BidFloorCur),
 			})
 			continue
 		}
 
 		if resolvedBidFloor > 0 {
-			thisImp.BidFloorCur = "USD"
-			thisImp.BidFloor = resolvedBidFloor
+			imp.BidFloorCur = "USD"
+			imp.BidFloor = resolvedBidFloor
 		}
 
 		if request.User != nil {
 			userCopy := *request.User
-
-			target, err := updateExtWithIabAttribute(rubiconExt.Visitor, userCopy.Data, []int{4})
+			target, err := updateUserRpTargetWithFpdAttributes(rubiconExt.Visitor, userCopy)
 			if err != nil {
 				errs = append(errs, err)
 				continue
 			}
+
 			userExtRP := rubiconUserExt{RP: rubiconUserExtRP{Target: target}}
 
 			if request.User.Ext != nil {
@@ -822,6 +791,10 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 				errs = append(errs, err)
 				continue
 			}
+			userCopy.Geo = nil
+			userCopy.Yob = 0
+			userCopy.Gender = ""
+
 			rubiconRequest.User = &userCopy
 		}
 
@@ -832,13 +805,13 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 			rubiconRequest.Device = &deviceCopy
 		}
 
-		isVideo := isVideo(thisImp)
+		isVideo := isVideo(imp)
 		if isVideo {
-			videoCopy := *thisImp.Video
+			videoCopy := *imp.Video
 
 			videoSizeId := rubiconExt.Video.VideoSizeID
 			if videoSizeId == 0 {
-				resolvedSizeId, err := resolveVideoSizeId(thisImp.Video.Placement, thisImp.Instl, thisImp.ID)
+				resolvedSizeId, err := resolveVideoSizeId(imp.Video.Placement, imp.Instl, imp.ID)
 				if err != nil {
 					errs = append(errs, err)
 					continue
@@ -853,23 +826,23 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 			}
 			videoExt := rubiconVideoExt{Skip: rubiconExt.Video.Skip, SkipDelay: rubiconExt.Video.SkipDelay, VideoType: videoType, RP: rubiconVideoExtRP{SizeID: videoSizeId}}
 			videoCopy.Ext, err = json.Marshal(&videoExt)
-			thisImp.Video = &videoCopy
-			thisImp.Banner = nil
+			imp.Video = &videoCopy
+			imp.Banner = nil
 		} else {
-			primarySizeID, altSizeIDs, err := parseRubiconSizes(thisImp.Banner.Format)
+			primarySizeID, altSizeIDs, err := parseRubiconSizes(imp.Banner.Format)
 			if err != nil {
 				errs = append(errs, err)
 				continue
 			}
 			bannerExt := rubiconBannerExt{RP: rubiconBannerExtRP{SizeID: primarySizeID, AltSizeIDs: altSizeIDs, MIME: "text/html"}}
-			bannerCopy := *thisImp.Banner
+			bannerCopy := *imp.Banner
 			bannerCopy.Ext, err = json.Marshal(&bannerExt)
 			if err != nil {
 				errs = append(errs, err)
 				continue
 			}
-			thisImp.Banner = &bannerCopy
-			thisImp.Video = nil
+			imp.Banner = &bannerCopy
+			imp.Video = nil
 		}
 
 		pubExt := rubiconPubExt{RP: rubiconPubExtRP{AccountID: rubiconExt.AccountId}}
@@ -878,12 +851,16 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 			siteCopy := *request.Site
 			siteExtRP := rubiconSiteExt{RP: rubiconSiteExtRP{SiteID: rubiconExt.SiteId}}
 			if siteCopy.Content != nil {
-				target, err := updateExtWithIabAttribute(nil, siteCopy.Content.Data, []int{1, 2})
-				if err != nil {
-					errs = append(errs, err)
-					continue
+				siteTarget := make(map[string]interface{})
+				updateExtWithIabAttribute(siteTarget, siteCopy.Content.Data, []int{1, 2, 5, 6})
+				if len(siteTarget) > 0 {
+					updatedSiteTarget, err := json.Marshal(siteTarget)
+					if err != nil {
+						errs = append(errs, err)
+						continue
+					}
+					siteExtRP.RP.Target = updatedSiteTarget
 				}
-				siteExtRP.RP.Target = target
 			}
 
 			siteCopy.Ext, err = json.Marshal(&siteExtRP)
@@ -910,7 +887,7 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ada
 			}
 		}
 
-		rubiconRequest.Imp = []openrtb2.Imp{thisImp}
+		rubiconRequest.Imp = []openrtb2.Imp{imp}
 		rubiconRequest.Cur = nil
 		rubiconRequest.Ext = nil
 
@@ -941,27 +918,272 @@ func resolveBidFloor(bidFloor float64, bidFloorCur string, reqInfo *adapters.Ext
 	return bidFloor, nil
 }
 
-func updateExtWithIabAttribute(target json.RawMessage, data []openrtb2.Data, segTaxes []int) (json.RawMessage, error) {
+func updateImpRpTargetWithFpdAttributes(extImp openrtb_ext.ExtImpRubicon, imp openrtb2.Imp,
+	site *openrtb2.Site, app *openrtb2.App) (json.RawMessage, error) {
+	existingTarget, _, _, err := jsonparser.Get(imp.Ext, "rp", "target")
+	if isNotKeyPathError(err) {
+		return nil, err
+	}
+	target, err := rawJSONToMap(existingTarget)
+	if err != nil {
+		return nil, err
+	}
+	err = populateFirstPartyDataAttributes(extImp.Inventory, target)
+	if err != nil {
+		return nil, err
+	}
+
+	if site != nil {
+		siteExtData, _, _, err := jsonparser.Get(site.Ext, "data")
+		if isNotKeyPathError(err) {
+			return nil, err
+		}
+		err = populateFirstPartyDataAttributes(siteExtData, target)
+		if err != nil {
+			return nil, err
+		}
+		if len(site.SectionCat) > 0 {
+			addStringArrayAttribute(site.SectionCat, target, "sectioncat")
+		}
+		if len(site.PageCat) > 0 {
+			addStringArrayAttribute(site.PageCat, target, "pagecat")
+		}
+		if site.Page != "" {
+			addStringAttribute(site.Page, target, "page")
+		}
+		if site.Ref != "" {
+			addStringAttribute(site.Ref, target, "ref")
+		}
+		if site.Search != "" {
+			addStringAttribute(site.Search, target, "search")
+		}
+	} else {
+		appExtData, _, _, err := jsonparser.Get(app.Ext, "data")
+		if isNotKeyPathError(err) {
+			return nil, err
+		}
+		err = populateFirstPartyDataAttributes(appExtData, target)
+		if err != nil {
+			return nil, err
+		}
+		if len(app.SectionCat) > 0 {
+			addStringArrayAttribute(app.SectionCat, target, "sectioncat")
+		}
+		if len(app.PageCat) > 0 {
+			addStringArrayAttribute(app.PageCat, target, "pagecat")
+		}
+	}
+
+	impExtContextAttributes, _, _, err := jsonparser.Get(imp.Ext, "context", "data")
+	if isNotKeyPathError(err) {
+		return nil, err
+	}
+
+	if len(impExtContextAttributes) > 0 {
+		err = populateFirstPartyDataAttributes(impExtContextAttributes, target)
+		if err != nil {
+			return nil, err
+		}
+	} else if impExtDataAttributes, _, _, err := jsonparser.Get(imp.Ext, "data"); err == nil && len(impExtDataAttributes) > 0 {
+		err = populateFirstPartyDataAttributes(impExtDataAttributes, target)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if isNotKeyPathError(err) {
+		return nil, err
+	}
+
+	if len(extImp.Keywords) > 0 {
+		addStringArrayAttribute(extImp.Keywords, target, "keywords")
+	}
+	updatedTarget, err := json.Marshal(target)
+	if err != nil {
+		return nil, err
+	}
+	return updatedTarget, nil
+}
+
+func isNotKeyPathError(err error) bool {
+	return err != nil && err != jsonparser.KeyPathNotFoundError
+}
+
+func addStringAttribute(attribute string, target map[string]interface{}, attributeName string) {
+	target[attributeName] = [1]string{attribute}
+}
+
+func addStringArrayAttribute(attribute []string, target map[string]interface{}, attributeName string) {
+	target[attributeName] = attribute
+}
+
+func getAdSlot(imp openrtb2.Imp) (string, error) {
+	var adSlot string
+	var parsingError error
+	jsonparser.EachKey(imp.Ext, func(idx int, value []byte, vt jsonparser.ValueType, err error) {
+		switch idx {
+		case 0:
+			adServerContextName, err := jsonparser.GetString(value, "name")
+			if isNotKeyPathError(err) {
+				parsingError = err
+				return
+			}
+			if adServerContextName == "gam" {
+				contextAdSlot, err := jsonparser.GetString(value, "adslot")
+				if isNotKeyPathError(err) {
+					parsingError = err
+					return
+				}
+				adSlot = contextAdSlot
+			}
+		}
+	}, []string{"context", "data", "adserver"})
+
+	if parsingError != nil {
+		return "", parsingError
+	}
+
+	if adSlot != "" {
+		return adSlot, nil
+	}
+
+	jsonparser.EachKey(imp.Ext, func(idx int, value []byte, vt jsonparser.ValueType, err error) {
+		switch idx {
+		case 0:
+			adServerDataName, err := jsonparser.GetString(value, "name")
+			if isNotKeyPathError(err) {
+				parsingError = err
+				return
+			}
+			if adServerDataName == "gam" {
+				dataAdSlot, err := jsonparser.GetString(value, "adslot")
+				if isNotKeyPathError(err) {
+					parsingError = err
+					return
+				}
+				adSlot = dataAdSlot
+			}
+		}
+	}, []string{"data", "adserver"})
+
+	if parsingError != nil {
+		return "", parsingError
+	}
+
+	return adSlot, nil
+}
+
+func updateUserRpTargetWithFpdAttributes(visitor json.RawMessage, user openrtb2.User) (json.RawMessage, error) {
+	existingTarget, _, _, err := jsonparser.Get(user.Ext, "rp", "target")
+	if isNotKeyPathError(err) {
+		return nil, err
+	}
+	target, err := rawJSONToMap(existingTarget)
+	if err != nil {
+		return nil, err
+	}
+	err = populateFirstPartyDataAttributes(visitor, target)
+	if err != nil {
+		return nil, err
+	}
+	userExtData, _, _, err := jsonparser.Get(user.Ext, "data")
+	if isNotKeyPathError(err) {
+		return nil, err
+	}
+	err = populateFirstPartyDataAttributes(userExtData, target)
+	if err != nil {
+		return nil, err
+	}
+	updateExtWithIabAttribute(target, user.Data, []int{4})
+
+	updatedTarget, err := json.Marshal(target)
+	if err != nil {
+		return nil, err
+	}
+	return updatedTarget, nil
+}
+
+func updateExtWithIabAttribute(target map[string]interface{}, data []openrtb2.Data, segTaxes []int) {
 	var segmentIdsToCopy = getSegmentIdsToCopy(data, segTaxes)
 	if len(segmentIdsToCopy) == 0 {
-		return target, nil
+		return
+	}
+
+	target["iab"] = segmentIdsToCopy
+}
+
+func populateFirstPartyDataAttributes(source json.RawMessage, target map[string]interface{}) error {
+	sourceAsMap, err := rawJSONToMap(source)
+	if err != nil {
+		return err
+	}
+
+	for key, val := range sourceAsMap {
+		switch typedValue := val.(type) {
+		case string:
+			target[key] = [1]string{typedValue}
+		case float64:
+			if typedValue == float64(int(typedValue)) {
+				target[key] = [1]string{strconv.Itoa(int(typedValue))}
+			}
+		case bool:
+			target[key] = [1]string{strconv.FormatBool(typedValue)}
+		case []interface{}:
+			if isStringArray(typedValue) {
+				target[key] = typedValue
+			}
+			if isBoolArray(typedValue) {
+				target[key] = convertToStringArray(typedValue)
+			}
+		}
+	}
+	return nil
+}
+
+func isStringArray(array []interface{}) bool {
+	for _, val := range array {
+		if _, ok := val.(string); !ok {
+			return false
+		}
+	}
+
+	return true
+}
+
+func isBoolArray(array []interface{}) bool {
+	for _, val := range array {
+		if _, ok := val.(bool); !ok {
+			return false
+		}
 	}
 
-	extRPTarget := make(map[string]interface{})
+	return true
+}
 
-	if target != nil {
-		if err := json.Unmarshal(target, &extRPTarget); err != nil {
-			return nil, &errortypes.BadInput{Message: err.Error()}
+func convertToStringArray(arr []interface{}) []string {
+	var stringArray []string
+	for _, val := range arr {
+		if boolVal, ok := val.(bool); ok {
+			stringArray = append(stringArray, strconv.FormatBool(boolVal))
 		}
 	}
 
-	extRPTarget["iab"] = segmentIdsToCopy
+	return stringArray
+}
+
+func rawJSONToMap(message json.RawMessage) (map[string]interface{}, error) {
+	if message == nil {
+		return make(map[string]interface{}), nil
+	}
 
-	jsonTarget, err := json.Marshal(&extRPTarget)
+	return mapFromRawJSON(message)
+}
+func mapFromRawJSON(message json.RawMessage) (map[string]interface{}, error) {
+	targetAsMap := make(map[string]interface{})
+	err := json.Unmarshal(message, &targetAsMap)
 	if err != nil {
-		return nil, &errortypes.BadInput{Message: err.Error()}
+		return nil, err
 	}
-	return jsonTarget, nil
+	return targetAsMap, nil
 }
 
 func getSegmentIdsToCopy(data []openrtb2.Data, segTaxValues []int) []string {
diff --git a/adapters/yssp/yssp.go b/adapters/yahoossp/yahoossp.go
similarity index 93%
rename from adapters/yssp/yssp.go
rename to adapters/yahoossp/yahoossp.go
index a73398ca..652d57f9 100644
--- a/adapters/yssp/yssp.go
+++ b/adapters/yahoossp/yahoossp.go
@@ -1,4 +1,4 @@
-package yssp
+package yahoossp
 
 import (
 	"encoding/json"
@@ -41,8 +41,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 			continue
 		}
 
-		var ysspExt openrtb_ext.ExtImpYSSP
-		err = json.Unmarshal(bidderExt.Bidder, &ysspExt)
+		var yahoosspExt openrtb_ext.ExtImpYahooSSP
+		err = json.Unmarshal(bidderExt.Bidder, &yahoosspExt)
 		if err != nil {
 			err = &errortypes.BadInput{
 				Message: fmt.Sprintf("imp #%d: %s", idx, err.Error()),
@@ -64,7 +64,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 			reqCopy.App = &appCopy
 		}
 
-		if err := changeRequestForBidService(&reqCopy, &ysspExt); err != nil {
+		if err := changeRequestForBidService(&reqCopy, &yahoosspExt); err != nil {
 			errors = append(errors, err)
 			continue
 		}
@@ -147,7 +147,7 @@ func getImpInfo(impId string, imps []openrtb2.Imp) (bool, openrtb_ext.BidType) {
 	return exists, mediaType
 }
 
-func changeRequestForBidService(request *openrtb2.BidRequest, extension *openrtb_ext.ExtImpYSSP) error {
+func changeRequestForBidService(request *openrtb2.BidRequest, extension *openrtb_ext.ExtImpYahooSSP) error {
 	/* Always override the tag ID and (site ID or app ID) of the request */
 	request.Imp[0].TagID = extension.Pos
 	if request.Site != nil {
@@ -180,7 +180,7 @@ func changeRequestForBidService(request *openrtb2.BidRequest, extension *openrtb
 	return nil
 }
 
-// Builder builds a new instance of the YSSP adapter for the given bidder with the given config.
+// Builder builds a new instance of the YahooSSP adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
 	bidder := &adapter{
 		URI: config.Endpoint,
diff --git a/cache/dummycache/dummycache.go b/cache/dummycache/dummycache.go
index 8cf9f2c4..02fe726d 100644
--- a/cache/dummycache/dummycache.go
+++ b/cache/dummycache/dummycache.go
@@ -38,11 +38,6 @@ func (s *accountService) Get(id string) (*cache.Account, error) {
 	}, nil
 }
 
-// Set will always return nil since this is a dummy service
-func (s *accountService) Set(account *cache.Account) error {
-	return nil
-}
-
 // ConfigService not supported, always returns an error
 type configService struct {
 	c string
diff --git a/cache/filecache/filecache.go b/cache/filecache/filecache.go
index 0c1ba435..7bc4bea4 100644
--- a/cache/filecache/filecache.go
+++ b/cache/filecache/filecache.go
@@ -103,11 +103,6 @@ func (s *accountService) Get(id string) (*cache.Account, error) {
 	}, nil
 }
 
-// Set will always return nil since this is a dummy service
-func (s *accountService) Set(account *cache.Account) error {
-	return nil
-}
-
 // ConfigService not supported, always returns an error
 type configService struct {
 	shared *shared
diff --git a/cache/legacy.go b/cache/legacy.go
index 427ec74d..19c5ae5a 100644
--- a/cache/legacy.go
+++ b/cache/legacy.go
@@ -25,7 +25,6 @@ type Cache interface {
 
 type AccountsService interface {
 	Get(string) (*Account, error)
-	Set(*Account) error
 }
 
 type ConfigService interface {
diff --git a/cache/postgrescache/postgrescache.go b/cache/postgrescache/postgrescache.go
index df8b8fe4..2333e082 100644
--- a/cache/postgrescache/postgrescache.go
+++ b/cache/postgrescache/postgrescache.go
@@ -104,11 +104,6 @@ func decodeAccount(b []byte) *cache.Account {
 	return &account
 }
 
-// Set the account in postgres and the lru cache
-func (s *accountService) Set(account *cache.Account) error {
-	return nil
-}
-
 // ConfigService
 type configService struct {
 	shared *shared
diff --git a/config/config.go b/config/config.go
index a8d85f1f..75203b9f 100644
--- a/config/config.go
+++ b/config/config.go
@@ -869,6 +869,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.viewdeos.endpoint", "http://ghb.sync.viewdeos.com/pbs/ortb")
 	v.SetDefault("adapters.visx.endpoint", "https://t.visx.net/s2s_bid?wrapperType=s2s_prebid_standard:0.1.0")
 	v.SetDefault("adapters.vrtcal.endpoint", "http://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804")
+	v.SetDefault("adapters.yahoossp.disabled", true)
 	v.SetDefault("adapters.yeahmobi.endpoint", "https://{{.Host}}/prebid/bid")
 	v.SetDefault("adapters.yieldlab.endpoint", "https://ad.yieldlab.net/yp/")
 	v.SetDefault("adapters.yieldmo.endpoint", "https://ads.yieldmo.com/exchange/prebid-server")
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 579d6687..44b05f40 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -548,7 +548,7 @@ func (deps *endpointDeps) validateImp(imp *openrtb2.Imp, aliases map[string]stri
 		return []error{fmt.Errorf("request.imp[%d] must contain at least one of \"banner\", \"video\", \"audio\", or \"native\"", index)}
 	}
 
-	if err := validateBanner(imp.Banner, index); err != nil {
+	if err := validateBanner(imp.Banner, index, isInterstitial(imp)); err != nil {
 		return []error{err}
 	}
 
@@ -576,7 +576,11 @@ func (deps *endpointDeps) validateImp(imp *openrtb2.Imp, aliases map[string]stri
 	return nil
 }
 
-func validateBanner(banner *openrtb2.Banner, impIndex int) error {
+func isInterstitial(imp *openrtb2.Imp) bool {
+	return imp.Instl == 1
+}
+
+func validateBanner(banner *openrtb2.Banner, impIndex int, isInterstitial bool) error {
 	if banner == nil {
 		return nil
 	}
@@ -606,7 +610,7 @@ func validateBanner(banner *openrtb2.Banner, impIndex int) error {
 	}
 
 	hasRootSize := banner.H != nil && banner.W != nil && *banner.H > 0 && *banner.W > 0
-	if !hasRootSize && len(banner.Format) == 0 {
+	if !hasRootSize && len(banner.Format) == 0 && !isInterstitial {
 		return fmt.Errorf("request.imp[%d].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements.", impIndex)
 	}
 
diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/banner-no-size.json b/endpoints/openrtb2/sample-requests/invalid-whole/banner-no-size.json
new file mode 100644
index 00000000..555fba70
--- /dev/null
+++ b/endpoints/openrtb2/sample-requests/invalid-whole/banner-no-size.json
@@ -0,0 +1,24 @@
+{
+    "description": "Banner Ad Without Sizes Defined",
+    "mockBidRequest": {
+        "id": "some-request-id",
+        "site": {
+            "page": "test.somepage.com"
+        },
+        "imp": [{
+            "id": "some-imp-id",
+            "banner": {},
+            "ext": {
+                "prebid": {
+                    "bidder": {
+                        "appnexus": {
+                            "placementId": 12883451
+                        }
+                    }
+                }
+            }
+        }]
+    },
+    "expectedErrorMessage": "Invalid request: request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements.",
+    "expectedReturnCode": 400
+}
diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/interstitial-no-size.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/interstitial-no-size.json
new file mode 100644
index 00000000..6100769a
--- /dev/null
+++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/interstitial-no-size.json
@@ -0,0 +1,38 @@
+{
+    "description": "Interstitial Banner Ad Without Sizes Defined",
+    "mockBidRequest": {
+        "id": "some-request-id",
+        "site": {
+            "page": "test.somepage.com"
+        },
+        "imp": [{
+            "id": "some-imp-id",
+            "instl": 1,
+            "banner": {},
+            "ext": {
+                "prebid": {
+                    "bidder": {
+                        "appnexus": {
+                            "placementId": 12883451
+                        }
+                    }
+                }
+            }
+        }]
+    },
+    "expectedBidResponse": {
+        "id": "some-request-id",
+        "seatbid": [{
+            "bid": [{
+                "id": "appnexus-bid",
+                "impid": "",
+                "price": 0
+            }],
+            "seat": "appnexus-bids"
+        }],
+        "bidid": "test bid id",
+        "cur": "USD",
+        "nbr": 0
+    },
+    "expectedReturnCode": 200
+}
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 630f18b6..c796df06 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -120,11 +120,11 @@ import (
 	"github.com/prebid/prebid-server/adapters/valueimpression"
 	"github.com/prebid/prebid-server/adapters/visx"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
+	"github.com/prebid/prebid-server/adapters/yahoossp"
 	"github.com/prebid/prebid-server/adapters/yeahmobi"
 	"github.com/prebid/prebid-server/adapters/yieldlab"
 	"github.com/prebid/prebid-server/adapters/yieldmo"
 	"github.com/prebid/prebid-server/adapters/yieldone"
-	"github.com/prebid/prebid-server/adapters/yssp"
 	"github.com/prebid/prebid-server/adapters/zeroclickfraud"
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
@@ -252,15 +252,16 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderUnicorn:           unicorn.Builder,
 		openrtb_ext.BidderUnruly:            unruly.Builder,
 		openrtb_ext.BidderValueImpression:   valueimpression.Builder,
-		openrtb_ext.BidderVerizonMedia:      yssp.Builder,
+		openrtb_ext.BidderVerizonMedia:      yahoossp.Builder,
 		openrtb_ext.BidderViewdeos:          adtelligent.Builder,
 		openrtb_ext.BidderVisx:              visx.Builder,
 		openrtb_ext.BidderVrtcal:            vrtcal.Builder,
+		openrtb_ext.BidderYahooSSP:          yahoossp.Builder,
 		openrtb_ext.BidderYeahmobi:          yeahmobi.Builder,
 		openrtb_ext.BidderYieldlab:          yieldlab.Builder,
 		openrtb_ext.BidderYieldmo:           yieldmo.Builder,
 		openrtb_ext.BidderYieldone:          yieldone.Builder,
-		openrtb_ext.BidderYSSP:              yssp.Builder,
+		openrtb_ext.BidderYSSP:              yahoossp.Builder,
 		openrtb_ext.BidderZeroClickFraud:    zeroclickfraud.Builder,
 	}
 }
diff --git a/metrics/config/metrics.go b/metrics/config/metrics.go
index 34d874d9..51ba8caf 100644
--- a/metrics/config/metrics.go
+++ b/metrics/config/metrics.go
@@ -47,7 +47,7 @@ func NewMetricsEngine(cfg *config.Configuration, adapterList []openrtb_ext.Bidde
 	} else if len(engineList) == 1 {
 		returnEngine.MetricsEngine = engineList[0]
 	} else {
-		returnEngine.MetricsEngine = &DummyMetricsEngine{}
+		returnEngine.MetricsEngine = &NilMetricsEngine{}
 	}
 
 	return &returnEngine
@@ -258,117 +258,118 @@ func (me *MultiMetricsEngine) RecordAdapterGDPRRequestBlocked(adapter openrtb_ex
 	}
 }
 
-// DummyMetricsEngine is a Noop metrics engine in case no metrics are configured. (may also be useful for tests)
-type DummyMetricsEngine struct{}
+// NilMetricsEngine implements the MetricsEngine interface where no metrics are actually captured. This is
+// used if no metric backend is configured and also for tests.
+type NilMetricsEngine struct{}
 
 // RecordRequest as a noop
-func (me *DummyMetricsEngine) RecordRequest(labels metrics.Labels) {
+func (me *NilMetricsEngine) RecordRequest(labels metrics.Labels) {
 }
 
 // RecordConnectionAccept as a noop
-func (me *DummyMetricsEngine) RecordConnectionAccept(success bool) {
+func (me *NilMetricsEngine) RecordConnectionAccept(success bool) {
 }
 
 // RecordConnectionClose as a noop
-func (me *DummyMetricsEngine) RecordConnectionClose(success bool) {
+func (me *NilMetricsEngine) RecordConnectionClose(success bool) {
 }
 
 // RecordImps as a noop
-func (me *DummyMetricsEngine) RecordImps(implabels metrics.ImpLabels) {
+func (me *NilMetricsEngine) RecordImps(implabels metrics.ImpLabels) {
 }
 
 // RecordLegacyImps as a noop
-func (me *DummyMetricsEngine) RecordLegacyImps(labels metrics.Labels, numImps int) {
+func (me *NilMetricsEngine) RecordLegacyImps(labels metrics.Labels, numImps int) {
 }
 
 // RecordRequestTime as a noop
-func (me *DummyMetricsEngine) RecordRequestTime(labels metrics.Labels, length time.Duration) {
+func (me *NilMetricsEngine) RecordRequestTime(labels metrics.Labels, length time.Duration) {
 }
 
 // RecordStoredDataFetchTime as a noop
-func (me *DummyMetricsEngine) RecordStoredDataFetchTime(labels metrics.StoredDataLabels, length time.Duration) {
+func (me *NilMetricsEngine) RecordStoredDataFetchTime(labels metrics.StoredDataLabels, length time.Duration) {
 }
 
 // RecordStoredDataError as a noop
-func (me *DummyMetricsEngine) RecordStoredDataError(labels metrics.StoredDataLabels) {
+func (me *NilMetricsEngine) RecordStoredDataError(labels metrics.StoredDataLabels) {
 }
 
 // RecordAdapterPanic as a noop
-func (me *DummyMetricsEngine) RecordAdapterPanic(labels metrics.AdapterLabels) {
+func (me *NilMetricsEngine) RecordAdapterPanic(labels metrics.AdapterLabels) {
 }
 
 // RecordAdapterRequest as a noop
-func (me *DummyMetricsEngine) RecordAdapterRequest(labels metrics.AdapterLabels) {
+func (me *NilMetricsEngine) RecordAdapterRequest(labels metrics.AdapterLabels) {
 }
 
 // RecordAdapterConnections as a noop
-func (me *DummyMetricsEngine) RecordAdapterConnections(bidderName openrtb_ext.BidderName, connWasReused bool, connWaitTime time.Duration) {
+func (me *NilMetricsEngine) RecordAdapterConnections(bidderName openrtb_ext.BidderName, connWasReused bool, connWaitTime time.Duration) {
 }
 
 // RecordDNSTime as a noop
-func (me *DummyMetricsEngine) RecordDNSTime(dnsLookupTime time.Duration) {
+func (me *NilMetricsEngine) RecordDNSTime(dnsLookupTime time.Duration) {
 }
 
 // RecordTLSHandshakeTime as a noop
-func (me *DummyMetricsEngine) RecordTLSHandshakeTime(tlsHandshakeTime time.Duration) {
+func (me *NilMetricsEngine) RecordTLSHandshakeTime(tlsHandshakeTime time.Duration) {
 }
 
 // RecordAdapterBidReceived as a noop
-func (me *DummyMetricsEngine) RecordAdapterBidReceived(labels metrics.AdapterLabels, bidType openrtb_ext.BidType, hasAdm bool) {
+func (me *NilMetricsEngine) RecordAdapterBidReceived(labels metrics.AdapterLabels, bidType openrtb_ext.BidType, hasAdm bool) {
 }
 
 // RecordAdapterPrice as a noop
-func (me *DummyMetricsEngine) RecordAdapterPrice(labels metrics.AdapterLabels, cpm float64) {
+func (me *NilMetricsEngine) RecordAdapterPrice(labels metrics.AdapterLabels, cpm float64) {
 }
 
 // RecordAdapterTime as a noop
-func (me *DummyMetricsEngine) RecordAdapterTime(labels metrics.AdapterLabels, length time.Duration) {
+func (me *NilMetricsEngine) RecordAdapterTime(labels metrics.AdapterLabels, length time.Duration) {
 }
 
 // RecordCookieSync as a noop
-func (me *DummyMetricsEngine) RecordCookieSync(status metrics.CookieSyncStatus) {
+func (me *NilMetricsEngine) RecordCookieSync(status metrics.CookieSyncStatus) {
 }
 
 // RecordSyncerRequest as a noop
-func (me *DummyMetricsEngine) RecordSyncerRequest(key string, status metrics.SyncerCookieSyncStatus) {
+func (me *NilMetricsEngine) RecordSyncerRequest(key string, status metrics.SyncerCookieSyncStatus) {
 }
 
 // RecordSetUid as a noop
-func (me *DummyMetricsEngine) RecordSetUid(status metrics.SetUidStatus) {
+func (me *NilMetricsEngine) RecordSetUid(status metrics.SetUidStatus) {
 }
 
 // RecordSyncerSet as a noop
-func (me *DummyMetricsEngine) RecordSyncerSet(key string, status metrics.SyncerSetUidStatus) {
+func (me *NilMetricsEngine) RecordSyncerSet(key string, status metrics.SyncerSetUidStatus) {
 }
 
 // RecordStoredReqCacheResult as a noop
-func (me *DummyMetricsEngine) RecordStoredReqCacheResult(cacheResult metrics.CacheResult, inc int) {
+func (me *NilMetricsEngine) RecordStoredReqCacheResult(cacheResult metrics.CacheResult, inc int) {
 }
 
 // RecordStoredImpCacheResult as a noop
-func (me *DummyMetricsEngine) RecordStoredImpCacheResult(cacheResult metrics.CacheResult, inc int) {
+func (me *NilMetricsEngine) RecordStoredImpCacheResult(cacheResult metrics.CacheResult, inc int) {
 }
 
 // RecordAccountCacheResult as a noop
-func (me *DummyMetricsEngine) RecordAccountCacheResult(cacheResult metrics.CacheResult, inc int) {
+func (me *NilMetricsEngine) RecordAccountCacheResult(cacheResult metrics.CacheResult, inc int) {
 }
 
 // RecordPrebidCacheRequestTime as a noop
-func (me *DummyMetricsEngine) RecordPrebidCacheRequestTime(success bool, length time.Duration) {
+func (me *NilMetricsEngine) RecordPrebidCacheRequestTime(success bool, length time.Duration) {
 }
 
 // RecordRequestQueueTime as a noop
-func (me *DummyMetricsEngine) RecordRequestQueueTime(success bool, requestType metrics.RequestType, length time.Duration) {
+func (me *NilMetricsEngine) RecordRequestQueueTime(success bool, requestType metrics.RequestType, length time.Duration) {
 }
 
 // RecordTimeoutNotice as a noop
-func (me *DummyMetricsEngine) RecordTimeoutNotice(success bool) {
+func (me *NilMetricsEngine) RecordTimeoutNotice(success bool) {
 }
 
 // RecordRequestPrivacy as a noop
-func (me *DummyMetricsEngine) RecordRequestPrivacy(privacy metrics.PrivacyLabels) {
+func (me *NilMetricsEngine) RecordRequestPrivacy(privacy metrics.PrivacyLabels) {
 }
 
 // RecordAdapterGDPRRequestBlocked as a noop
-func (me *DummyMetricsEngine) RecordAdapterGDPRRequestBlocked(adapter openrtb_ext.BidderName) {
+func (me *NilMetricsEngine) RecordAdapterGDPRRequestBlocked(adapter openrtb_ext.BidderName) {
 }
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 88f816c2..69ed1f42 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -195,6 +195,7 @@ const (
 	BidderVisx              BidderName = "visx"
 	BidderViewdeos          BidderName = "viewdeos"
 	BidderVrtcal            BidderName = "vrtcal"
+	BidderYahooSSP          BidderName = "yahoossp"
 	BidderYeahmobi          BidderName = "yeahmobi"
 	BidderYieldlab          BidderName = "yieldlab"
 	BidderYieldmo           BidderName = "yieldmo"
@@ -328,6 +329,7 @@ func CoreBidderNames() []BidderName {
 		BidderViewdeos,
 		BidderVisx,
 		BidderVrtcal,
+		BidderYahooSSP,
 		BidderYeahmobi,
 		BidderYieldlab,
 		BidderYieldmo,
diff --git a/openrtb_ext/imp_rubicon.go b/openrtb_ext/imp_rubicon.go
index ee43d965..f9b15ed3 100644
--- a/openrtb_ext/imp_rubicon.go
+++ b/openrtb_ext/imp_rubicon.go
@@ -10,6 +10,7 @@ type ExtImpRubicon struct {
 	SiteId    int                `json:"siteId"`
 	ZoneId    int                `json:"zoneId"`
 	Inventory json.RawMessage    `json:"inventory,omitempty"`
+	Keywords  []string           `json:"keywords,omitempty"`
 	Visitor   json.RawMessage    `json:"visitor,omitempty"`
 	Video     rubiconVideoParams `json:"video"`
 	Debug     impExtRubiconDebug `json:"debug,omitempty"`
diff --git a/openrtb_ext/imp_yahoossp.go b/openrtb_ext/imp_yahoossp.go
new file mode 100644
index 00000000..e3183c86
--- /dev/null
+++ b/openrtb_ext/imp_yahoossp.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+// ExtImpYahooSSP defines the contract for bidrequest.imp[i].ext.yahoossp
+type ExtImpYahooSSP struct {
+	Dcn string `json:"dcn"`
+	Pos string `json:"pos"`
+}
diff --git a/openrtb_ext/imp_yssp.go b/openrtb_ext/imp_yssp.go
deleted file mode 100644
index 054836ec..00000000
--- a/openrtb_ext/imp_yssp.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package openrtb_ext
-
-// ExtImpYSSP defines the contract for bidrequest.imp[i].ext.yssp
-type ExtImpYSSP struct {
-	Dcn string `json:"dcn"`
-	Pos string `json:"pos"`
-}
diff --git a/static/bidder-info/yahoossp.yaml b/static/bidder-info/yahoossp.yaml
new file mode 100644
index 00000000..06d0cb18
--- /dev/null
+++ b/static/bidder-info/yahoossp.yaml
@@ -0,0 +1,15 @@
+maintainer:
+  email: "hb-fe-tech@oath.com"
+gvlVendorID: 25
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+  site:
+    mediaTypes:
+      - banner
+userSync:
+  # yahoossp supports user syncing, but requires configuration by the host. contact this
+  # bidder directly at the email address in this file to ask about enabling user sync.
+  supports:
+    - redirect
\ No newline at end of file
diff --git a/static/bidder-params/yahoossp.json b/static/bidder-params/yahoossp.json
new file mode 100644
index 00000000..9d971149
--- /dev/null
+++ b/static/bidder-params/yahoossp.json
@@ -0,0 +1,19 @@
+{
+	"$schema": "http://json-schema.org/draft-04/schema#",
+	"title": "YahooSSP Adapter Params",
+	"description": "A schema which validates params accepted by the YahooSSP adapter",
+	"type": "object",
+	"properties": {
+		"dcn": {
+			"type": "string",
+			"minLength": 1,
+			"description": "Site ID provided by One Mobile"
+		},
+		"pos": {
+			"type": "string",
+			"minLength": 1,
+			"description": "Placement ID"
+		}
+	},
+	"required": ["dcn", "pos"]
+}


Test patch:
diff --git a/adapters/rubicon/rubicon_test.go b/adapters/rubicon/rubicon_test.go
index 2d4c962b..9bfa04fa 100644
--- a/adapters/rubicon/rubicon_test.go
+++ b/adapters/rubicon/rubicon_test.go
@@ -35,6 +35,12 @@ type rubiAppendTrackerUrlTestScenario struct {
 	expected string
 }
 
+type rubiPopulateFpdAttributesScenario struct {
+	source json.RawMessage
+	target map[string]interface{}
+	result map[string]interface{}
+}
+
 type rubiSetNetworkIdTestScenario struct {
 	bidExt            *openrtb_ext.ExtBidPrebid
 	buyer             string
@@ -1277,7 +1283,10 @@ func TestOpenRTBRequestWithImpAndAdSlotIncluded(t *testing.T) {
 				},
 				"context": {
 					"data": {
-						"adslot": "///test-adslot"
+                        "adserver": {
+                             "adslot": "/test-adslot",
+                             "name": "gam"
+                        }
 					}
 				}
 			}`),
@@ -1302,14 +1311,52 @@ func TestOpenRTBRequestWithImpAndAdSlotIncluded(t *testing.T) {
 	if err := json.Unmarshal(rubiconReq.Imp[0].Ext, &rpImpExt); err != nil {
 		t.Fatal("Error unmarshalling imp.ext")
 	}
+	assert.Equal(t, rpImpExt.GPID, "/test-adslot")
+}
 
-	rubiconExtInventory := make(map[string]interface{})
-	if err := json.Unmarshal(rpImpExt.RP.Target, &rubiconExtInventory); err != nil {
-		t.Fatal("Error unmarshalling imp.ext.rp.target")
+func TestOpenRTBFirstPartyDataPopulating(t *testing.T) {
+	testScenarios := []rubiPopulateFpdAttributesScenario{
+		{
+			source: json.RawMessage(`{"sourceKey": ["sourceValue", "sourceValue2"]}`),
+			target: map[string]interface{}{"targetKey": []interface{}{"targetValue"}},
+			result: map[string]interface{}{"targetKey": []interface{}{"targetValue"}, "sourceKey": []interface{}{"sourceValue", "sourceValue2"}},
+		},
+		{
+			source: json.RawMessage(`{"sourceKey": ["sourceValue", "sourceValue2"]}`),
+			target: make(map[string]interface{}),
+			result: map[string]interface{}{"sourceKey": []interface{}{"sourceValue", "sourceValue2"}},
+		},
+		{
+			source: json.RawMessage(`{"sourceKey": "sourceValue"}`),
+			target: make(map[string]interface{}),
+			result: map[string]interface{}{"sourceKey": [1]string{"sourceValue"}},
+		},
+		{
+			source: json.RawMessage(`{"sourceKey": true, "sourceKey2": [true, false, true]}`),
+			target: make(map[string]interface{}),
+			result: map[string]interface{}{"sourceKey": [1]string{"true"}, "sourceKey2": []string{"true", "false", "true"}},
+		},
+		{
+			source: json.RawMessage(`{"sourceKey": 1, "sourceKey2": [1, 2, 3]}`),
+			target: make(map[string]interface{}),
+			result: map[string]interface{}{"sourceKey": [1]string{"1"}},
+		},
+		{
+			source: json.RawMessage(`{"sourceKey": 1, "sourceKey2": 3.23}`),
+			target: make(map[string]interface{}),
+			result: map[string]interface{}{"sourceKey": [1]string{"1"}},
+		},
+		{
+			source: json.RawMessage(`{"sourceKey": {}}`),
+			target: make(map[string]interface{}),
+			result: make(map[string]interface{}),
+		},
 	}
 
-	assert.Equal(t, "test-adslot", rubiconExtInventory["dfp_ad_unit_code"],
-		"Unexpected dfp_ad_unit_code: %s", rubiconExtInventory["dfp_ad_unit_code"])
+	for _, scenario := range testScenarios {
+		populateFirstPartyDataAttributes(scenario.source, scenario.target)
+		assert.Equal(t, scenario.result, scenario.target)
+	}
 }
 
 func TestOpenRTBRequestWithBadvOverflowed(t *testing.T) {
diff --git a/adapters/rubicon/rubicontest/exemplary/app-imp-fpd.json b/adapters/rubicon/rubicontest/exemplary/app-imp-fpd.json
new file mode 100644
index 00000000..eec396f8
--- /dev/null
+++ b/adapters/rubicon/rubicontest/exemplary/app-imp-fpd.json
@@ -0,0 +1,411 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    },
+    "app": {
+      "pagecat": [
+        "val1",
+        "val2"
+      ],
+      "sectioncat": [
+        "sectionCat1",
+        "sectionCat2"
+      ],
+      "ext": {
+        "data": {
+          "attr1": "val1",
+          "attr2": [
+            "val21",
+            "val22"
+          ],
+          "attr3": true,
+          "attr4": [
+            true,
+            false,
+            true,
+            true
+          ],
+          "attr5": 3,
+          "attr6": [
+            1,
+            2,
+            3
+          ],
+          "attr7": 1.23
+        }
+      }
+    },
+    "user": {
+      "yob": 2000,
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "gender": "f",
+      "data": [
+        {
+          "ext": {
+            "segtax": 4
+          },
+          "segment": [
+            {
+              "id": "idToCopy"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": "someValue"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": "4"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": 4
+          },
+          "segment": [
+            {
+              "id": "idToCopy2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": [
+              4
+            ]
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied3"
+            }
+          ]
+        }
+      ],
+      "ext": {
+        "data": {
+          "attr1": "val1",
+          "attr2": [
+            "val21",
+            "val22"
+          ],
+          "attr3": true,
+          "attr4": [
+            true,
+            false,
+            true,
+            true
+          ],
+          "attr5": 3,
+          "attr6": [
+            1,
+            2,
+            3
+          ],
+          "attr7": 1.23
+        }
+      }
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "instl": 1,
+        "video": {
+          "placement": 3,
+          "mimes": [
+            "video/mp4"
+          ],
+          "protocols": [
+            2,
+            5
+          ],
+          "w": 1024,
+          "h": 576
+        },
+        "ext": {
+          "context": {
+            "data": {
+              "adserver": {
+                "name": "gam",
+                "adslot": "someAdSlot"
+              },
+              "dataAttr1": "dataVal1",
+              "dataAttr2": "dataVal2"
+            }
+          },
+          "bidder": {
+            "video": {
+            },
+            "accountId": 1001,
+            "siteId": 113932,
+            "zoneId": 535510
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "uri?tk_xint=pbs-test-tracker",
+        "body": {
+          "id": "test-request-id",
+          "device": {
+            "ext": {
+              "rp": {
+                "pixelratio": 0
+              }
+            },
+            "ip": "123.123.123.123",
+            "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+          },
+          "app": {
+            "pagecat": [
+              "val1",
+              "val2"
+            ],
+            "sectioncat": [
+              "sectionCat1",
+              "sectionCat2"
+            ],
+            "ext": {
+              "rp": {
+                "site_id": 113932
+              }
+            },
+            "publisher": {
+              "ext": {
+                "rp": {
+                  "account_id": 1001
+                }
+              }
+            }
+          },
+          "user": {
+            "data": [
+              {
+                "ext": {
+                  "segtax": 4
+                },
+                "segment": [
+                  {
+                    "id": "idToCopy"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": "someValue"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": "4"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": 4
+                },
+                "segment": [
+                  {
+                    "id": "idToCopy2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": [
+                    4
+                  ]
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied3"
+                  }
+                ]
+              }
+            ],
+            "ext": {
+              "rp": {
+                "target": {
+                  "attr1": [
+                    "val1"
+                  ],
+                  "attr2": [
+                    "val21",
+                    "val22"
+                  ],
+                  "attr3": [
+                    "true"
+                  ],
+                  "attr4": [
+                    "true",
+                    "false",
+                    "true",
+                    "true"
+                  ],
+                  "attr5": [
+                    "3"
+                  ],
+                  "iab": [
+                    "idToCopy",
+                    "idToCopy2"
+                  ]
+                }
+              }
+            }
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "instl": 1,
+              "video": {
+                "placement": 3,
+                "ext": {
+                  "rp": {
+                    "size_id": 203
+                  }
+                },
+                "mimes": [
+                  "video/mp4"
+                ],
+                "protocols": [
+                  2,
+                  5
+                ],
+                "w": 1024,
+                "h": 576
+              },
+              "ext": {
+                "gpid": "someAdSlot",
+                "rp": {
+                  "target": {
+                    "dataAttr1": [
+                      "dataVal1"
+                    ],
+                    "dataAttr2": [
+                      "dataVal2"
+                    ],
+                    "attr1": [
+                      "val1"
+                    ],
+                    "attr2": [
+                      "val21",
+                      "val22"
+                    ],
+                    "attr3": [
+                      "true"
+                    ],
+                    "attr4": [
+                      "true",
+                      "false",
+                      "true",
+                      "true"
+                    ],
+                    "attr5": [
+                      "3"
+                    ],
+                    "pagecat": [
+                      "val1",
+                      "val2"
+                    ],
+                    "sectioncat": [
+                      "sectionCat1",
+                      "sectionCat2"
+                    ]
+                  },
+                  "track": {
+                    "mint": "",
+                    "mint_version": ""
+                  },
+                  "zone_id": 535510
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test_bid_id",
+                  "impid": "test-imp-id",
+                  "price": 0.27543,
+                  "adm": "some-test-ad",
+                  "cid": "test_cid",
+                  "crid": "test_crid",
+                  "dealid": "test_dealid",
+                  "ext": {
+                    "prebid": {
+                      "type": "video"
+                    }
+                  }
+                }
+              ],
+              "seat": "adman"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test_bid_id",
+            "impid": "test-imp-id",
+            "price": 0.27543,
+            "adm": "some-test-ad",
+            "cid": "test_cid",
+            "crid": "test_crid",
+            "dealid": "test_dealid",
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/rubicon/rubicontest/exemplary/simple-video.json b/adapters/rubicon/rubicontest/exemplary/simple-video.json
index 7e5274f2..592f9fb2 100644
--- a/adapters/rubicon/rubicontest/exemplary/simple-video.json
+++ b/adapters/rubicon/rubicontest/exemplary/simple-video.json
@@ -10,6 +10,10 @@
       "bundle": "com.wls.testwlsapplication"
     },
     "site": {
+      "pagecat": [
+        "val1",
+        "val2"
+      ],
       "content": {
         "data": [
           {
@@ -49,6 +53,13 @@
       }
     },
     "user": {
+      "yob": 2000,
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "gender": "f",
       "data": [
         {
           "ext": {
@@ -148,6 +159,10 @@
             "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
           },
           "site": {
+            "pagecat": [
+              "val1",
+              "val2"
+            ],
             "content": {
               "data": [
                 {
@@ -298,6 +313,12 @@
               },
               "ext": {
                 "rp": {
+                  "target": {
+                    "pagecat": [
+                      "val1",
+                      "val2"
+                    ]
+                  },
                   "track": {
                     "mint": "",
                     "mint_version": ""
diff --git a/adapters/rubicon/rubicontest/exemplary/site-imp-fpd.json b/adapters/rubicon/rubicontest/exemplary/site-imp-fpd.json
new file mode 100644
index 00000000..56f5ce61
--- /dev/null
+++ b/adapters/rubicon/rubicontest/exemplary/site-imp-fpd.json
@@ -0,0 +1,542 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    },
+    "site": {
+      "pagecat": [
+        "val1",
+        "val2"
+      ],
+      "sectioncat": [
+        "sectionCat1",
+        "sectionCat2"
+      ],
+      "page": "somePage",
+      "ref": "someRef",
+      "search": "someSearch",
+      "ext": {
+        "data": {
+          "attr1": "val1",
+          "attr2": [
+            "val21",
+            "val22"
+          ],
+          "attr3": true,
+          "attr4": [
+            true,
+            false,
+            true,
+            true
+          ],
+          "attr5": 3,
+          "attr6": [
+            1,
+            2,
+            3
+          ],
+          "attr7": 1.23
+        }
+      },
+      "content": {
+        "data": [
+          {
+            "ext": {
+              "segtax": 1
+            },
+            "segment": [
+              {
+                "id": "idToCopy"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": "someValue"
+            },
+            "segment": [
+              {
+                "id": "shouldNotBeCopied"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": "2"
+            },
+            "segment": [
+              {
+                "id": "shouldNotBeCopied2"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": 2
+            },
+            "segment": [
+              {
+                "id": "idToCopy2"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": 5
+            },
+            "segment": [
+              {
+                "id": "idToCopy3"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": 6
+            },
+            "segment": [
+              {
+                "id": "idToCopy4"
+              }
+            ]
+          },
+          {
+            "ext": {
+              "segtax": [
+                2
+              ]
+            },
+            "segment": [
+              {
+                "id": "shouldNotBeCopied3"
+              }
+            ]
+          }
+        ]
+      }
+    },
+    "user": {
+      "yob": 2000,
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "gender": "f",
+      "data": [
+        {
+          "ext": {
+            "segtax": 4
+          },
+          "segment": [
+            {
+              "id": "idToCopy"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": "someValue"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": "4"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": 4
+          },
+          "segment": [
+            {
+              "id": "idToCopy2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": [
+              4
+            ]
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied3"
+            }
+          ]
+        }
+      ]
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "instl": 1,
+        "video": {
+          "placement": 3,
+          "mimes": [
+            "video/mp4"
+          ],
+          "protocols": [
+            2,
+            5
+          ],
+          "w": 1024,
+          "h": 576
+        },
+        "ext": {
+          "data": {
+            "adserver": {
+              "name": "gam",
+              "adslot": "someAdSlot"
+            },
+            "dataAttr1": "dataVal1",
+            "dataAttr2": "dataVal2"
+          },
+          "bidder": {
+            "video": {
+            },
+            "accountId": 1001,
+            "siteId": 113932,
+            "zoneId": 535510
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "uri?tk_xint=pbs-test-tracker",
+        "body": {
+          "id": "test-request-id",
+          "device": {
+            "ext": {
+              "rp": {
+                "pixelratio": 0
+              }
+            },
+            "ip": "123.123.123.123",
+            "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+          },
+          "site": {
+            "pagecat": [
+              "val1",
+              "val2"
+            ],
+            "sectioncat": [
+              "sectionCat1",
+              "sectionCat2"
+            ],
+            "page": "somePage",
+            "ref": "someRef",
+            "search": "someSearch",
+            "content": {
+              "data": [
+                {
+                  "ext": {
+                    "segtax": 1
+                  },
+                  "segment": [
+                    {
+                      "id": "idToCopy"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": "someValue"
+                  },
+                  "segment": [
+                    {
+                      "id": "shouldNotBeCopied"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": "2"
+                  },
+                  "segment": [
+                    {
+                      "id": "shouldNotBeCopied2"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": 2
+                  },
+                  "segment": [
+                    {
+                      "id": "idToCopy2"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": 5
+                  },
+                  "segment": [
+                    {
+                      "id": "idToCopy3"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": 6
+                  },
+                  "segment": [
+                    {
+                      "id": "idToCopy4"
+                    }
+                  ]
+                },
+                {
+                  "ext": {
+                    "segtax": [
+                      2
+                    ]
+                  },
+                  "segment": [
+                    {
+                      "id": "shouldNotBeCopied3"
+                    }
+                  ]
+                }
+              ]
+            },
+            "ext": {
+              "rp": {
+                "site_id": 113932,
+                "target": {
+                  "iab": [
+                    "idToCopy",
+                    "idToCopy2",
+                    "idToCopy3",
+                    "idToCopy4"
+                  ]
+                }
+              }
+            },
+            "publisher": {
+              "ext": {
+                "rp": {
+                  "account_id": 1001
+                }
+              }
+            }
+          },
+          "user": {
+            "data": [
+              {
+                "ext": {
+                  "segtax": 4
+                },
+                "segment": [
+                  {
+                    "id": "idToCopy"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": "someValue"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": "4"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": 4
+                },
+                "segment": [
+                  {
+                    "id": "idToCopy2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": [
+                    4
+                  ]
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied3"
+                  }
+                ]
+              }
+            ],
+            "ext": {
+              "rp": {
+                "target": {
+                  "iab": [
+                    "idToCopy",
+                    "idToCopy2"
+                  ]
+                }
+              }
+            }
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "instl": 1,
+              "video": {
+                "placement": 3,
+                "ext": {
+                  "rp": {
+                    "size_id": 203
+                  }
+                },
+                "mimes": [
+                  "video/mp4"
+                ],
+                "protocols": [
+                  2,
+                  5
+                ],
+                "w": 1024,
+                "h": 576
+              },
+              "ext": {
+                "gpid": "someAdSlot",
+                "rp": {
+                  "target": {
+                    "dataAttr1": [
+                      "dataVal1"
+                    ],
+                    "dataAttr2": [
+                      "dataVal2"
+                    ],
+                    "attr1": [
+                      "val1"
+                    ],
+                    "attr2": [
+                      "val21",
+                      "val22"
+                    ],
+                    "attr3": [
+                      "true"
+                    ],
+                    "attr4": [
+                      "true",
+                      "false",
+                      "true",
+                      "true"
+                    ],
+                    "attr5": [
+                      "3"
+                    ],
+                    "page": [
+                      "somePage"
+                    ],
+                    "ref": [
+                      "someRef"
+                    ],
+                    "search": [
+                      "someSearch"
+                    ],
+                    "pagecat": [
+                      "val1",
+                      "val2"
+                    ],
+                    "sectioncat": [
+                      "sectionCat1",
+                      "sectionCat2"
+                    ]
+                  },
+                  "track": {
+                    "mint": "",
+                    "mint_version": ""
+                  },
+                  "zone_id": 535510
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test_bid_id",
+                  "impid": "test-imp-id",
+                  "price": 0.27543,
+                  "adm": "some-test-ad",
+                  "cid": "test_cid",
+                  "crid": "test_crid",
+                  "dealid": "test_dealid",
+                  "ext": {
+                    "prebid": {
+                      "type": "video"
+                    }
+                  }
+                }
+              ],
+              "seat": "adman"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test_bid_id",
+            "impid": "test-imp-id",
+            "price": 0.27543,
+            "adm": "some-test-ad",
+            "cid": "test_cid",
+            "crid": "test_crid",
+            "dealid": "test_dealid",
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/rubicon/rubicontest/exemplary/user-fpd.json b/adapters/rubicon/rubicontest/exemplary/user-fpd.json
new file mode 100644
index 00000000..b2be736f
--- /dev/null
+++ b/adapters/rubicon/rubicontest/exemplary/user-fpd.json
@@ -0,0 +1,344 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    },
+    "site": {
+      "page": "somePage",
+      "ref": "someRef",
+      "search": "someSearch"
+    },
+    "user": {
+      "yob": 2000,
+      "geo": {
+        "country": "USA",
+        "lat": 47.627500,
+        "lon": -122.346200
+      },
+      "gender": "f",
+      "data": [
+        {
+          "ext": {
+            "segtax": 4
+          },
+          "segment": [
+            {
+              "id": "idToCopy"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": "someValue"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": "4"
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": 4
+          },
+          "segment": [
+            {
+              "id": "idToCopy2"
+            }
+          ]
+        },
+        {
+          "ext": {
+            "segtax": [
+              4
+            ]
+          },
+          "segment": [
+            {
+              "id": "shouldNotBeCopied3"
+            }
+          ]
+        }
+      ],
+      "keywords": "someKeywords",
+      "ext": {
+        "rp": {
+          "target": {
+            "someKey": "someValue"
+          }
+        },
+        "data": {
+          "dataKey1": "dataValue1",
+          "dataKey2": [
+            "dataValue2",
+            "dataValue3"
+          ],
+          "dataKey3": true
+        }
+      }
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "instl": 1,
+        "video": {
+          "placement": 3,
+          "mimes": [
+            "video/mp4"
+          ],
+          "protocols": [
+            2,
+            5
+          ],
+          "w": 1024,
+          "h": 576
+        },
+        "ext": {
+          "data": {
+            "adserver": {
+              "name": "gam",
+              "adslot": "someAdSlot"
+            },
+            "dataAttr1": "dataVal1",
+            "dataAttr2": "dataVal2"
+          },
+          "bidder": {
+            "video": {
+            },
+            "accountId": 1001,
+            "siteId": 113932,
+            "zoneId": 535510
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "uri?tk_xint=pbs-test-tracker",
+        "body": {
+          "id": "test-request-id",
+          "device": {
+            "ext": {
+              "rp": {
+                "pixelratio": 0
+              }
+            },
+            "ip": "123.123.123.123",
+            "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+          },
+          "site": {
+            "page": "somePage",
+            "ref": "someRef",
+            "search": "someSearch",
+            "ext": {
+              "rp": {
+                "site_id": 113932
+              }
+            },
+            "publisher": {
+              "ext": {
+                "rp": {
+                  "account_id": 1001
+                }
+              }
+            }
+          },
+          "user": {
+            "data": [
+              {
+                "ext": {
+                  "segtax": 4
+                },
+                "segment": [
+                  {
+                    "id": "idToCopy"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": "someValue"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": "4"
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": 4
+                },
+                "segment": [
+                  {
+                    "id": "idToCopy2"
+                  }
+                ]
+              },
+              {
+                "ext": {
+                  "segtax": [
+                    4
+                  ]
+                },
+                "segment": [
+                  {
+                    "id": "shouldNotBeCopied3"
+                  }
+                ]
+              }
+            ],
+            "ext": {
+              "rp": {
+                "target": {
+                  "someKey": "someValue",
+                  "dataKey1": [
+                    "dataValue1"
+                  ],
+                  "dataKey2": [
+                    "dataValue2",
+                    "dataValue3"
+                  ],
+                  "dataKey3": [
+                    "true"
+                  ],
+                  "iab": [
+                    "idToCopy",
+                    "idToCopy2"
+                  ]
+                }
+              }
+            },
+            "keywords": "someKeywords"
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "instl": 1,
+              "video": {
+                "placement": 3,
+                "ext": {
+                  "rp": {
+                    "size_id": 203
+                  }
+                },
+                "mimes": [
+                  "video/mp4"
+                ],
+                "protocols": [
+                  2,
+                  5
+                ],
+                "w": 1024,
+                "h": 576
+              },
+              "ext": {
+                "gpid": "someAdSlot",
+                "rp": {
+                  "target": {
+                    "dataAttr1": [
+                      "dataVal1"
+                    ],
+                    "dataAttr2": [
+                      "dataVal2"
+                    ],
+                    "page": [
+                      "somePage"
+                    ],
+                    "ref": [
+                      "someRef"
+                    ],
+                    "search": [
+                      "someSearch"
+                    ]
+                  },
+                  "track": {
+                    "mint": "",
+                    "mint_version": ""
+                  },
+                  "zone_id": 535510
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test_bid_id",
+                  "impid": "test-imp-id",
+                  "price": 0.27543,
+                  "adm": "some-test-ad",
+                  "cid": "test_cid",
+                  "crid": "test_crid",
+                  "dealid": "test_dealid",
+                  "ext": {
+                    "prebid": {
+                      "type": "video"
+                    }
+                  }
+                }
+              ],
+              "seat": "adman"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test_bid_id",
+            "impid": "test-imp-id",
+            "price": 0.27543,
+            "adm": "some-test-ad",
+            "cid": "test_cid",
+            "crid": "test_crid",
+            "dealid": "test_dealid",
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/rubicon/rubicontest/supplemental/no-site-content-data.json b/adapters/rubicon/rubicontest/supplemental/no-site-content-data.json
index 0be214da..a1e13815 100644
--- a/adapters/rubicon/rubicontest/supplemental/no-site-content-data.json
+++ b/adapters/rubicon/rubicontest/supplemental/no-site-content-data.json
@@ -10,6 +10,10 @@
       "bundle": "com.wls.testwlsapplication"
     },
     "site": {
+      "pagecat": [
+        "val1",
+        "val2"
+      ],
       "content": {
       }
     },
@@ -113,6 +117,10 @@
             "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
           },
           "site": {
+            "pagecat": [
+              "val1",
+              "val2"
+            ],
             "content": {
             },
             "ext": {
@@ -221,6 +229,12 @@
               },
               "ext": {
                 "rp": {
+                  "target": {
+                    "pagecat": [
+                      "val1",
+                      "val2"
+                    ]
+                  },
                   "track": {
                     "mint": "",
                     "mint_version": ""
diff --git a/adapters/rubicon/rubicontest/supplemental/no-site-content.json b/adapters/rubicon/rubicontest/supplemental/no-site-content.json
index 2e830a2d..6630799b 100644
--- a/adapters/rubicon/rubicontest/supplemental/no-site-content.json
+++ b/adapters/rubicon/rubicontest/supplemental/no-site-content.json
@@ -10,6 +10,10 @@
       "bundle": "com.wls.testwlsapplication"
     },
     "site": {
+      "pagecat": [
+        "val1",
+        "val2"
+      ]
     },
     "user": {
       "data": [
@@ -111,6 +115,10 @@
             "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
           },
           "site": {
+            "pagecat": [
+              "val1",
+              "val2"
+            ],
             "ext": {
               "rp": {
                 "site_id": 113932
@@ -217,6 +225,12 @@
               },
               "ext": {
                 "rp": {
+                  "target": {
+                    "pagecat": [
+                      "val1",
+                      "val2"
+                    ]
+                  },
                   "track": {
                     "mint": "",
                     "mint_version": ""
diff --git a/adapters/yssp/params_test.go b/adapters/yahoossp/params_test.go
similarity index 61%
rename from adapters/yssp/params_test.go
rename to adapters/yahoossp/params_test.go
index 66146377..47d8d268 100644
--- a/adapters/yssp/params_test.go
+++ b/adapters/yahoossp/params_test.go
@@ -1,4 +1,4 @@
-package yssp
+package yahoossp
 
 import (
 	"encoding/json"
@@ -7,11 +7,11 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-// This file actually intends to test static/bidder-params/yssp.json
+// This file actually intends to test static/bidder-params/yahoossp.json
 //
-// These also validate the format of the external API: request.imp[i].ext.yssp
+// These also validate the format of the external API: request.imp[i].ext.yahoossp
 
-// TestValidParams makes sure that the yssp schema accepts all imp.ext fields which we intend to support.
+// TestValidParams makes sure that the yahoossp schema accepts all imp.ext fields which we intend to support.
 func TestValidParams(t *testing.T) {
 	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
 	if err != nil {
@@ -19,13 +19,13 @@ func TestValidParams(t *testing.T) {
 	}
 
 	for _, validParam := range validParams {
-		if err := validator.Validate(openrtb_ext.BidderYSSP, json.RawMessage(validParam)); err != nil {
-			t.Errorf("Schema rejected yssp params: %s", validParam)
+		if err := validator.Validate(openrtb_ext.BidderYahooSSP, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected yahoossp params: %s", validParam)
 		}
 	}
 }
 
-// TestInvalidParams makes sure that the yssp schema rejects all the imp.ext fields we don't support.
+// TestInvalidParams makes sure that the yahoossp schema rejects all the imp.ext fields we don't support.
 func TestInvalidParams(t *testing.T) {
 	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
 	if err != nil {
@@ -33,7 +33,7 @@ func TestInvalidParams(t *testing.T) {
 	}
 
 	for _, invalidParam := range invalidParams {
-		if err := validator.Validate(openrtb_ext.BidderYSSP, json.RawMessage(invalidParam)); err == nil {
+		if err := validator.Validate(openrtb_ext.BidderYahooSSP, json.RawMessage(invalidParam)); err == nil {
 			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
 		}
 	}
diff --git a/adapters/yssp/yssp_test.go b/adapters/yahoossp/yahoossp_test.go
similarity index 56%
rename from adapters/yssp/yssp_test.go
rename to adapters/yahoossp/yahoossp_test.go
index ee99d672..214457c0 100644
--- a/adapters/yssp/yssp_test.go
+++ b/adapters/yahoossp/yahoossp_test.go
@@ -1,4 +1,4 @@
-package yssp
+package yahoossp
 
 import (
 	"testing"
@@ -9,8 +9,8 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-func TestYSSPBidderEndpointConfig(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderYSSP, config.Adapter{
+func TestYahooSSPBidderEndpointConfig(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderYahooSSP, config.Adapter{
 		Endpoint: "http://localhost/bid",
 	})
 
@@ -18,17 +18,17 @@ func TestYSSPBidderEndpointConfig(t *testing.T) {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
 	}
 
-	bidderYSSP := bidder.(*adapter)
+	bidderYahooSSP := bidder.(*adapter)
 
-	assert.Equal(t, "http://localhost/bid", bidderYSSP.URI)
+	assert.Equal(t, "http://localhost/bid", bidderYahooSSP.URI)
 }
 
 func TestJsonSamples(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderYSSP, config.Adapter{})
+	bidder, buildErr := Builder(openrtb_ext.BidderYahooSSP, config.Adapter{})
 
 	if buildErr != nil {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
 	}
 
-	adapterstest.RunJSONBidderTest(t, "yssptest", bidder)
+	adapterstest.RunJSONBidderTest(t, "yahoossptest", bidder)
 }
diff --git a/adapters/yssp/yssptest/exemplary/simple-app-banner.json b/adapters/yahoossp/yahoossptest/exemplary/simple-app-banner.json
similarity index 98%
rename from adapters/yssp/yssptest/exemplary/simple-app-banner.json
rename to adapters/yahoossp/yahoossptest/exemplary/simple-app-banner.json
index a28913f8..319e22e3 100644
--- a/adapters/yssp/yssptest/exemplary/simple-app-banner.json
+++ b/adapters/yahoossp/yahoossptest/exemplary/simple-app-banner.json
@@ -77,7 +77,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yssp",
+              "seat": "yahoossp",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yssp/yssptest/exemplary/simple-banner.json b/adapters/yahoossp/yahoossptest/exemplary/simple-banner.json
similarity index 98%
rename from adapters/yssp/yssptest/exemplary/simple-banner.json
rename to adapters/yahoossp/yahoossptest/exemplary/simple-banner.json
index 4a71473b..344bbe9a 100644
--- a/adapters/yssp/yssptest/exemplary/simple-banner.json
+++ b/adapters/yahoossp/yahoossptest/exemplary/simple-banner.json
@@ -77,7 +77,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yssp",
+              "seat": "yahoossp",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yssp/yssptest/supplemental/empty-banner-format.json b/adapters/yahoossp/yahoossptest/supplemental/empty-banner-format.json
similarity index 100%
rename from adapters/yssp/yssptest/supplemental/empty-banner-format.json
rename to adapters/yahoossp/yahoossptest/supplemental/empty-banner-format.json
diff --git a/adapters/yssp/yssptest/supplemental/invalid-banner-width.json b/adapters/yahoossp/yahoossptest/supplemental/invalid-banner-width.json
similarity index 100%
rename from adapters/yssp/yssptest/supplemental/invalid-banner-width.json
rename to adapters/yahoossp/yahoossptest/supplemental/invalid-banner-width.json
diff --git a/adapters/yssp/yssptest/supplemental/non-banner-bids-ignored.json b/adapters/yahoossp/yahoossptest/supplemental/non-banner-bids-ignored.json
similarity index 98%
rename from adapters/yssp/yssptest/supplemental/non-banner-bids-ignored.json
rename to adapters/yahoossp/yahoossptest/supplemental/non-banner-bids-ignored.json
index 94772a4b..6f40e2a9 100644
--- a/adapters/yssp/yssptest/supplemental/non-banner-bids-ignored.json
+++ b/adapters/yahoossp/yahoossptest/supplemental/non-banner-bids-ignored.json
@@ -74,7 +74,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yssp",
+              "seat": "yahoossp",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yssp/yssptest/supplemental/required-nobidder-info.json b/adapters/yahoossp/yahoossptest/supplemental/required-nobidder-info.json
similarity index 100%
rename from adapters/yssp/yssptest/supplemental/required-nobidder-info.json
rename to adapters/yahoossp/yahoossptest/supplemental/required-nobidder-info.json
diff --git a/adapters/yssp/yssptest/supplemental/server-error.json b/adapters/yahoossp/yahoossptest/supplemental/server-error.json
similarity index 100%
rename from adapters/yssp/yssptest/supplemental/server-error.json
rename to adapters/yahoossp/yahoossptest/supplemental/server-error.json
diff --git a/adapters/yssp/yssptest/supplemental/server-response-wrong-impid.json b/adapters/yahoossp/yahoossptest/supplemental/server-response-wrong-impid.json
similarity index 98%
rename from adapters/yssp/yssptest/supplemental/server-response-wrong-impid.json
rename to adapters/yahoossp/yahoossptest/supplemental/server-response-wrong-impid.json
index 1e893127..5b33f3af 100644
--- a/adapters/yssp/yssptest/supplemental/server-response-wrong-impid.json
+++ b/adapters/yahoossp/yahoossptest/supplemental/server-response-wrong-impid.json
@@ -76,7 +76,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yssp",
+              "seat": "yahoossp",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "wrong",
diff --git a/adapters/yssp/yssptest/params/race/banner.json b/adapters/yssp/yssptest/params/race/banner.json
deleted file mode 100644
index 739ec3c0..00000000
--- a/adapters/yssp/yssptest/params/race/banner.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "dcn": "2345",
-  "pos": "header"
-}
diff --git a/endpoints/auction_test.go b/endpoints/auction_test.go
index 522b38ba..1a30e025 100644
--- a/endpoints/auction_test.go
+++ b/endpoints/auction_test.go
@@ -357,7 +357,7 @@ func TestCacheVideoOnly(t *testing.T) {
 	}, nil, nil)
 	prebid_cache_client.InitPrebidCache(server.URL)
 	var labels = &metrics.Labels{}
-	if err := cacheVideoOnly(bids, ctx, &auction{cfg: cfg, syncersByBidder: syncersByBidder, gdprPerms: gdprPerms, metricsEngine: &metricsConf.DummyMetricsEngine{}}, labels); err != nil {
+	if err := cacheVideoOnly(bids, ctx, &auction{cfg: cfg, syncersByBidder: syncersByBidder, gdprPerms: gdprPerms, metricsEngine: &metricsConf.NilMetricsEngine{}}, labels); err != nil {
 		t.Errorf("Prebid cache failed: %v \n", err)
 		return
 	}
@@ -637,18 +637,18 @@ func TestWriteAuctionError(t *testing.T) {
 }
 
 func TestPanicRecovery(t *testing.T) {
-	dummy := auction{
+	testAuction := auction{
 		cfg:             nil,
 		syncersByBidder: nil,
 		gdprPerms: &auctionMockPermissions{
 			allowBidderSync:  false,
 			allowHostCookies: false,
 		},
-		metricsEngine: &metricsConf.DummyMetricsEngine{},
+		metricsEngine: &metricsConf.NilMetricsEngine{},
 	}
 	panicker := func(bidder *pbs.PBSBidder, blables metrics.AdapterLabels) {
 		panic("panic!")
 	}
-	recovered := dummy.recoverSafely(panicker)
+	recovered := testAuction.recoverSafely(panicker)
 	recovered(nil, metrics.AdapterLabels{})
 }
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index ae3c036a..656ee190 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -45,7 +45,7 @@ func TestGoodAmpRequests(t *testing.T) {
 		&mockAmpStoredReqFetcher{goodRequests},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -99,7 +99,7 @@ func TestAMPPageInfo(t *testing.T) {
 		&mockAmpStoredReqFetcher{stored},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -197,7 +197,7 @@ func TestGDPRConsent(t *testing.T) {
 			&mockAmpStoredReqFetcher{stored},
 			empty_fetcher.EmptyFetcher{},
 			&config.Configuration{MaxRequestSize: maxSize},
-			&metricsConfig.DummyMetricsEngine{},
+			&metricsConfig.NilMetricsEngine{},
 			analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 			map[string]string{},
 			[]byte{},
@@ -350,7 +350,7 @@ func TestCCPAConsent(t *testing.T) {
 			&mockAmpStoredReqFetcher{stored},
 			empty_fetcher.EmptyFetcher{},
 			&config.Configuration{MaxRequestSize: maxSize},
-			&metricsConfig.DummyMetricsEngine{},
+			&metricsConfig.NilMetricsEngine{},
 			analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 			map[string]string{},
 			[]byte{},
@@ -461,7 +461,7 @@ func TestConsentWarnings(t *testing.T) {
 			&mockAmpStoredReqFetcher{stored},
 			empty_fetcher.EmptyFetcher{},
 			&config.Configuration{MaxRequestSize: maxSize},
-			&metricsConfig.DummyMetricsEngine{},
+			&metricsConfig.NilMetricsEngine{},
 			analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 			map[string]string{},
 			[]byte{},
@@ -554,7 +554,7 @@ func TestNewAndLegacyConsentBothProvided(t *testing.T) {
 			&mockAmpStoredReqFetcher{stored},
 			empty_fetcher.EmptyFetcher{},
 			&config.Configuration{MaxRequestSize: maxSize},
-			&metricsConfig.DummyMetricsEngine{},
+			&metricsConfig.NilMetricsEngine{},
 			analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 			map[string]string{},
 			[]byte{},
@@ -606,7 +606,7 @@ func TestAMPSiteExt(t *testing.T) {
 		&mockAmpStoredReqFetcher{stored},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		nil,
 		nil,
@@ -643,7 +643,7 @@ func TestAmpBadRequests(t *testing.T) {
 		&mockAmpStoredReqFetcher{badRequests},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -674,7 +674,7 @@ func TestAmpDebug(t *testing.T) {
 		&mockAmpStoredReqFetcher{requests},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -747,7 +747,7 @@ func TestQueryParamOverrides(t *testing.T) {
 		&mockAmpStoredReqFetcher{requests},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -900,7 +900,7 @@ func (s formatOverrideSpec) execute(t *testing.T) {
 		&mockAmpStoredReqFetcher{requests},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -1340,7 +1340,7 @@ func AmpObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMe
 		mockAmpFetcher,
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize, GenerateRequestID: generateRequestID},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		logger,
 		map[string]string{},
 		[]byte{},
diff --git a/endpoints/openrtb2/auction_benchmark_test.go b/endpoints/openrtb2/auction_benchmark_test.go
index f2e0fb2a..2a1300d7 100644
--- a/endpoints/openrtb2/auction_benchmark_test.go
+++ b/endpoints/openrtb2/auction_benchmark_test.go
@@ -18,13 +18,13 @@ import (
 	"github.com/prebid/prebid-server/usersync"
 )
 
-// dummyServer returns the header bidding test ad. This response was scraped from a real appnexus server response.
-func dummyServer(w http.ResponseWriter, r *http.Request) {
+// benchmarkTestServer returns the header bidding test ad. This response was scraped from a real appnexus server response.
+func benchmarkTestServer(w http.ResponseWriter, r *http.Request) {
 	w.Write([]byte(`{"id":"some-request-id","seatbid":[{"bid":[{"id":"4625436751433509010","impid":"my-imp-id","price":0.5,"adm":"\u003cscript type=\"application/javascript\" src=\"http://nym1-ib.adnxs.com/ab?e=wqT_3QKABqAAAwAAAwDWAAUBCM-OiNAFELuV09Pqi86EVRj6t-7QyLin_REqLQkAAAECCOA_EQEHNAAA4D8ZAAAAgOtR4D8hERIAKREJoDDy5vwEOL4HQL4HSAJQ1suTDljhgEhgAGiRQHixhQSAAQGKAQNVU0SSBQbwUpgBrAKgAfoBqAEBsAEAuAECwAEDyAEC0AEA2AEA4AEB8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE1MTAwODIzODMpO3VmKCdyJywgMjk2ODExMTAsMh4A8JySAvkBIVR6WGNkQWk2MEljRUVOYkxrdzRZQUNEaGdFZ3dBRGdBUUFSSXZnZFE4dWI4QkZnQVlQX19fXzhQYUFCd0FYZ0JnQUVCaUFFQmtBRUJtQUVCb0FFQnFBRURzQUVBdVFFcGk0aURBQURnUDhFQktZdUlnd0FBNERfSkFTZlJKRUdtbi00XzJRRUFBQUFBQUFEd1AtQUJBUFVCBQ8oSmdDQUtBQ0FMVUMFEARMMAkI8ExNQUNBY2dDQWRBQ0FkZ0NBZUFDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEdXRDSEJMb0RDVTVaVFRJNk16STNOdy4umgItITh3aENuZzb8ALg0WUJJSUFRb0FEb0pUbGxOTWpvek1qYzPYAugH4ALH0wHyAhAKBkFEVl9JRBIGNCV1HPICEQoGQ1BHARMcBzE5Nzc5MzMBJwgFQ1AFE_B-ODUxMzU5NIADAYgDAZADAJgDFKADAaoDAMADrALIAwDYAwDgAwDoAwD4AwCABACSBAkvb3BlbnJ0YjKYBACoBACyBAwIABAAGAAgADAAOAC4BADABADIBADSBAlOWU0yOjMyNzfaBAIIAeAEAPAE1suTDogFAZgFAKAF_____wUDXAGqBQ9zb21lLXJlcXVlc3QtaWTABQDJBUmbTPA_0gUJCQAAAAAAAAAA2AUB4AUB\u0026s=61dc0e8770543def5a3a77b4589830d1274b26f1\u0026test=1\u0026pp=${AUCTION_PRICE}\u0026\"\u003e\u003c/script\u003e","adid":"29681110","adomain":["appnexus.com"],"iurl":"http://nym1-ib.adnxs.com/cr?id=29681110","cid":"958","crid":"29681110","w":300,"h":250,"ext":{"bidder":{"appnexus":{"brand_id":1,"auction_id":6127490747252132539,"bidder_id":2}}}}],"seat":"appnexus"}],"ext":{"debug":{"httpcalls":{"appnexus":[{"uri":"http://ib.adnxs.com/openrtb2","requestbody":"{\"id\":\"some-request-id\",\"imp\":[{\"id\":\"my-imp-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}]},\"ext\":{\"appnexus\":{\"placement_id\":12883451}}}],\"test\":1,\"tmax\":500}","responsebody":"{\"id\":\"some-request-id\",\"seatbid\":[{\"bid\":[{\"id\":\"4625436751433509010\",\"impid\":\"my-imp-id\",\"price\": 0.500000,\"adid\":\"29681110\",\"adm\":\"\u003cscript type=\\\"application/javascript\\\" src=\\\"http://nym1-ib.adnxs.com/ab?e=wqT_3QKABqAAAwAAAwDWAAUBCM-OiNAFELuV09Pqi86EVRj6t-7QyLin_REqLQkAAAECCOA_EQEHNAAA4D8ZAAAAgOtR4D8hERIAKREJoDDy5vwEOL4HQL4HSAJQ1suTDljhgEhgAGiRQHixhQSAAQGKAQNVU0SSBQbwUpgBrAKgAfoBqAEBsAEAuAECwAEDyAEC0AEA2AEA4AEB8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE1MTAwODIzODMpO3VmKCdyJywgMjk2ODExMTAsMh4A8JySAvkBIVR6WGNkQWk2MEljRUVOYkxrdzRZQUNEaGdFZ3dBRGdBUUFSSXZnZFE4dWI4QkZnQVlQX19fXzhQYUFCd0FYZ0JnQUVCaUFFQmtBRUJtQUVCb0FFQnFBRURzQUVBdVFFcGk0aURBQURnUDhFQktZdUlnd0FBNERfSkFTZlJKRUdtbi00XzJRRUFBQUFBQUFEd1AtQUJBUFVCBQ8oSmdDQUtBQ0FMVUMFEARMMAkI8ExNQUNBY2dDQWRBQ0FkZ0NBZUFDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEdXRDSEJMb0RDVTVaVFRJNk16STNOdy4umgItITh3aENuZzb8ALg0WUJJSUFRb0FEb0pUbGxOTWpvek1qYzPYAugH4ALH0wHyAhAKBkFEVl9JRBIGNCV1HPICEQoGQ1BHARMcBzE5Nzc5MzMBJwgFQ1AFE_B-ODUxMzU5NIADAYgDAZADAJgDFKADAaoDAMADrALIAwDYAwDgAwDoAwD4AwCABACSBAkvb3BlbnJ0YjKYBACoBACyBAwIABAAGAAgADAAOAC4BADABADIBADSBAlOWU0yOjMyNzfaBAIIAeAEAPAE1suTDogFAZgFAKAF_____wUDXAGqBQ9zb21lLXJlcXVlc3QtaWTABQDJBUmbTPA_0gUJCQAAAAAAAAAA2AUB4AUB\u0026s=61dc0e8770543def5a3a77b4589830d1274b26f1\u0026test=1\u0026pp=${AUCTION_PRICE}\u0026\\\"\u003e\u003c/script\u003e\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"h\": 250,\"w\": 300,\"ext\":{\"appnexus\":{\"brand_id\": 1,\"auction_id\": 6127490747252132539,\"bidder_id\": 2}}}],\"seat\":\"958\"}],\"bidid\":\"8271358638249766712\",\"cur\":\"USD\"}","status":200}]}},"responsetimemillis":{"appnexus":42}}}`))
 }
 
-// newDummyRequest returns a request which fetches the header bidding test ad.
-func newDummyRequest() *http.Request {
+// benchmarkBuildTestRequest returns a request which fetches the header bidding test ad.
+func benchmarkBuildTestRequest() *http.Request {
 	request, _ := http.NewRequest("POST", "/openrtb2/auction", strings.NewReader(`{
   "id": "some-request-id",
   "imp": [
@@ -57,7 +57,7 @@ func newDummyRequest() *http.Request {
 
 // BenchmarkOpenrtbEndpoint measures the performance of the endpoint, mocking out the external server dependency.
 func BenchmarkOpenrtbEndpoint(b *testing.B) {
-	server := httptest.NewServer(http.HandlerFunc(dummyServer))
+	server := httptest.NewServer(http.HandlerFunc(benchmarkTestServer))
 	defer server.Close()
 
 	var infos config.BidderInfos
@@ -67,7 +67,7 @@ func BenchmarkOpenrtbEndpoint(b *testing.B) {
 		return
 	}
 
-	nilMetrics := &metricsConfig.DummyMetricsEngine{}
+	nilMetrics := &metricsConfig.NilMetricsEngine{}
 
 	adapters, adaptersErr := exchange.BuildAdapters(server.Client(), &config.Configuration{}, infos, nilMetrics)
 	if adaptersErr != nil {
@@ -102,6 +102,6 @@ func BenchmarkOpenrtbEndpoint(b *testing.B) {
 
 	b.ResetTimer()
 	for n := 0; n < b.N; n++ {
-		endpoint(httptest.NewRecorder(), newDummyRequest(), nil)
+		endpoint(httptest.NewRecorder(), benchmarkBuildTestRequest(), nil)
 	}
 }
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index ebf18994..80124eec 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -436,7 +436,7 @@ func TestExplicitUserId(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		cfg,
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -478,7 +478,7 @@ func doRequest(t *testing.T, test testCase) (int, string) {
 			BlacklistedAcctMap: test.Config.getBlackListedAccountMap(),
 			AccountRequired:    test.Config.AccountRequired,
 		},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		disabledBidders,
 		[]byte(test.Config.AliasJSON),
@@ -542,7 +542,7 @@ func doBadAliasRequest(t *testing.T, filename string, expectMsg string) {
 		&mockStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		disabledBidders,
 		aliasJSON,
@@ -593,7 +593,7 @@ func TestNilExchange(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}), map[string]string{},
 		[]byte{},
 		openrtb_ext.BuildBidderMap())
@@ -614,7 +614,7 @@ func TestNilValidator(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -636,7 +636,7 @@ func TestExchangeError(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -759,7 +759,7 @@ func TestImplicitIPsEndToEnd(t *testing.T) {
 			&mockStoredReqFetcher{},
 			empty_fetcher.EmptyFetcher{},
 			cfg,
-			&metricsConfig.DummyMetricsEngine{},
+			&metricsConfig.NilMetricsEngine{},
 			analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 			map[string]string{},
 			[]byte{},
@@ -954,7 +954,7 @@ func TestImplicitDNTEndToEnd(t *testing.T) {
 			&mockStoredReqFetcher{},
 			empty_fetcher.EmptyFetcher{},
 			&config.Configuration{MaxRequestSize: maxSize},
-			&metricsConfig.DummyMetricsEngine{},
+			&metricsConfig.NilMetricsEngine{},
 			analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 			map[string]string{},
 			[]byte{},
@@ -1109,7 +1109,7 @@ func TestStoredRequests(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1160,7 +1160,7 @@ func TestStoredRequestGenerateUuid(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1230,7 +1230,7 @@ func TestOversizedRequest(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: int64(len(reqBody) - 1)},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1266,7 +1266,7 @@ func TestRequestSizeEdgeCase(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: int64(len(reqBody))},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1300,7 +1300,7 @@ func TestNoEncoding(t *testing.T) {
 		&mockStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -1376,7 +1376,7 @@ func TestContentType(t *testing.T) {
 		&mockStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -1697,7 +1697,7 @@ func TestValidateImpExt(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: int64(8096)},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{"disabledbidder": "The bidder 'disabledbidder' has been disabled."},
 		false,
@@ -1744,7 +1744,7 @@ func TestCurrencyTrunc(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1789,7 +1789,7 @@ func TestCCPAInvalid(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1838,7 +1838,7 @@ func TestNoSaleInvalid(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1890,7 +1890,7 @@ func TestValidateSourceTID(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		cfg,
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1932,7 +1932,7 @@ func TestSChainInvalid(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -2152,7 +2152,7 @@ func TestEidPermissionsInvalid(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -2403,7 +2403,7 @@ func TestIOS14EndToEnd(t *testing.T) {
 		&mockStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		[]byte{},
@@ -2432,7 +2432,7 @@ func TestAuctionWarnings(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: int64(len(reqBody))},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -2472,7 +2472,7 @@ func TestParseRequestParseImpInfoError(t *testing.T) {
 		empty_fetcher.EmptyFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: int64(len(reqBody))},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -3715,3 +3715,35 @@ type fakeUUIDGenerator struct {
 func (f fakeUUIDGenerator) Generate() (string, error) {
 	return f.id, f.err
 }
+
+func TestValidateBanner(t *testing.T) {
+	impIndex := 0
+
+	testCases := []struct {
+		description    string
+		banner         *openrtb2.Banner
+		impIndex       int
+		isInterstitial bool
+		expectedError  error
+	}{
+		{
+			description:    "isInterstitial Equals False (not set to 1)",
+			banner:         &openrtb2.Banner{W: nil, H: nil, Format: nil},
+			impIndex:       impIndex,
+			isInterstitial: false,
+			expectedError:  errors.New("request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements."),
+		},
+		{
+			description:    "isInterstitial Equals True (is set to 1)",
+			banner:         &openrtb2.Banner{W: nil, H: nil, Format: nil},
+			impIndex:       impIndex,
+			isInterstitial: true,
+			expectedError:  nil,
+		},
+	}
+
+	for _, test := range testCases {
+		result := validateBanner(test.banner, test.impIndex, test.isInterstitial)
+		assert.Equal(t, test.expectedError, result, test.description)
+	}
+}
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index 26d9f028..3163cd9d 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -1260,7 +1260,7 @@ func mockDeps(t *testing.T, ex *mockExchangeVideo) *endpointDeps {
 		&mockVideoStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1283,7 +1283,7 @@ func mockDepsAppendBidderNames(t *testing.T, ex *mockExchangeAppendBidderNames)
 		&mockVideoStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
@@ -1306,7 +1306,7 @@ func mockDepsNoBids(t *testing.T, ex *mockExchangeVideoNoBids) *endpointDeps {
 		&mockVideoStoredReqFetcher{},
 		empty_fetcher.EmptyFetcher{},
 		&config.Configuration{MaxRequestSize: maxSize},
-		&metricsConfig.DummyMetricsEngine{},
+		&metricsConfig.NilMetricsEngine{},
 		analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 		map[string]string{},
 		false,
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index 97694607..3388965f 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -234,7 +234,7 @@ func TestSetUIDEndpoint(t *testing.T) {
 		},
 	}
 
-	metrics := &metricsConf.DummyMetricsEngine{}
+	metrics := &metricsConf.NilMetricsEngine{}
 	for _, test := range testCases {
 		response := doRequest(makeRequest(test.uri, test.existingSyncs), metrics,
 			test.syncersBidderNameToKey, test.gdprAllowsHostCookies, test.gdprReturnsError, test.gdprMalformed)
@@ -379,7 +379,7 @@ func TestOptedOut(t *testing.T) {
 	cookie.SetOptOut(true)
 	addCookie(request, cookie)
 	syncersBidderNameToKey := map[string]string{"pubmatic": "pubmatic"}
-	metrics := &metricsConf.DummyMetricsEngine{}
+	metrics := &metricsConf.NilMetricsEngine{}
 	response := doRequest(request, metrics, syncersBidderNameToKey, true, false, false)
 
 	assert.Equal(t, http.StatusUnauthorized, response.Code)
diff --git a/exchange/adapter_util_test.go b/exchange/adapter_util_test.go
index a8e8ef5e..b3a05cdc 100644
--- a/exchange/adapter_util_test.go
+++ b/exchange/adapter_util_test.go
@@ -22,7 +22,7 @@ var (
 
 func TestBuildAdapters(t *testing.T) {
 	client := &http.Client{}
-	metricEngine := &metrics.DummyMetricsEngine{}
+	metricEngine := &metrics.NilMetricsEngine{}
 
 	appnexusBidder, _ := appnexus.Builder(openrtb_ext.BidderAppnexus, config.Adapter{})
 	appnexusBidderWithInfo := adapters.BuildInfoAwareBidder(appnexusBidder, infoEnabled)
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index 1a630a96..da31658e 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -91,7 +91,7 @@ func TestSingleBidder(t *testing.T) {
 		}
 		bidderImpl.bidResponse = mockBidderResponse
 
-		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, test.debugInfo)
+		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, test.debugInfo)
 		currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 
 		seatBid, errs := bidder.requestBid(ctx, &openrtb2.BidRequest{}, "test", bidAdjustment, currencyConverter.Rates(), &adapters.ExtraRequestInfo{}, true, false)
@@ -170,7 +170,7 @@ func TestRequestBidRemovesSensitiveHeaders(t *testing.T) {
 	debugInfo := &config.DebugInfo{Allow: true}
 	ctx := context.Background()
 
-	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
+	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	seatBid, errs := bidder.requestBid(ctx, &openrtb2.BidRequest{}, "test", 1, currencyConverter.Rates(), &adapters.ExtraRequestInfo{}, true, false)
 
@@ -210,7 +210,7 @@ func TestSetGPCHeader(t *testing.T) {
 	debugInfo := &config.DebugInfo{Allow: true}
 	ctx := context.Background()
 
-	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
+	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	seatBid, errs := bidder.requestBid(ctx, &openrtb2.BidRequest{}, "test", 1, currencyConverter.Rates(), &adapters.ExtraRequestInfo{GlobalPrivacyControlHeader: "1"}, true, false)
 
@@ -247,7 +247,7 @@ func TestSetGPCHeaderNil(t *testing.T) {
 	debugInfo := &config.DebugInfo{Allow: true}
 	ctx := context.Background()
 
-	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
+	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, debugInfo)
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	seatBid, errs := bidder.requestBid(ctx, &openrtb2.BidRequest{}, "test", 1, currencyConverter.Rates(), &adapters.ExtraRequestInfo{GlobalPrivacyControlHeader: "1"}, true, false)
 
@@ -305,7 +305,7 @@ func TestMultiBidder(t *testing.T) {
 			}},
 		bidResponse: mockBidderResponse,
 	}
-	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+	bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	seatBid, errs := bidder.requestBid(context.Background(), &openrtb2.BidRequest{}, "test", 1.0, currencyConverter.Rates(), &adapters.ExtraRequestInfo{}, true, true)
 
@@ -346,7 +346,7 @@ func TestBidderTimeout(t *testing.T) {
 		Bidder:     &mixedMultiBidder{},
 		BidderName: openrtb_ext.BidderAppnexus,
 		Client:     server.Client(),
-		me:         &metricsConfig.DummyMetricsEngine{},
+		me:         &metricsConfig.NilMetricsEngine{},
 	}
 
 	callInfo := bidder.doRequest(ctx, &adapters.RequestData{
@@ -389,7 +389,7 @@ func TestConnectionClose(t *testing.T) {
 		Bidder:     &mixedMultiBidder{},
 		Client:     server.Client(),
 		BidderName: openrtb_ext.BidderAppnexus,
-		me:         &metricsConfig.DummyMetricsEngine{},
+		me:         &metricsConfig.NilMetricsEngine{},
 	}
 
 	callInfo := bidder.doRequest(context.Background(), &adapters.RequestData{
@@ -659,7 +659,7 @@ func TestMultiCurrencies(t *testing.T) {
 		)
 
 		// Execute:
-		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 		currencyConverter := currency.NewRateConverter(
 			&http.Client{},
 			mockedHTTPServer.URL,
@@ -812,7 +812,7 @@ func TestMultiCurrencies_RateConverterNotSet(t *testing.T) {
 		}
 
 		// Execute:
-		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 		currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 		seatBid, errs := bidder.requestBid(
 			context.Background(),
@@ -974,7 +974,7 @@ func TestMultiCurrencies_RequestCurrencyPick(t *testing.T) {
 		}
 
 		// Execute:
-		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 		currencyConverter := currency.NewRateConverter(
 			&http.Client{},
 			mockedHTTPServer.URL,
@@ -1284,7 +1284,7 @@ func TestMobileNativeTypes(t *testing.T) {
 			},
 			bidResponse: tc.mockBidderResponse,
 		}
-		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+		bidder := adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 		currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 
 		seatBids, _ := bidder.requestBid(
@@ -1307,7 +1307,7 @@ func TestMobileNativeTypes(t *testing.T) {
 }
 
 func TestErrorReporting(t *testing.T) {
-	bidder := adaptBidder(&bidRejector{}, nil, &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+	bidder := adaptBidder(&bidRejector{}, nil, &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	bids, errs := bidder.requestBid(context.Background(), &openrtb2.BidRequest{}, "test", 1.0, currencyConverter.Rates(), &adapters.ExtraRequestInfo{}, true, false)
 	if bids != nil {
@@ -1631,7 +1631,7 @@ func TestTimeoutNotificationOff(t *testing.T) {
 		Bidder: bidderImpl,
 		Client: server.Client(),
 		config: bidderAdapterConfig{Debug: config.Debug{}},
-		me:     &metricsConfig.DummyMetricsEngine{},
+		me:     &metricsConfig.NilMetricsEngine{},
 	}
 	if tb, ok := bidder.Bidder.(adapters.TimeoutBidder); !ok {
 		t.Error("Failed to cast bidder to a TimeoutBidder")
@@ -1672,7 +1672,7 @@ func TestTimeoutNotificationOn(t *testing.T) {
 				},
 			},
 		},
-		me: &metricsConfig.DummyMetricsEngine{},
+		me: &metricsConfig.NilMetricsEngine{},
 	}
 
 	// Unwrap To Mimic exchange.go Casting Code
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 6258d121..9dcf9d66 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -60,13 +60,13 @@ func TestNewExchange(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
 
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
-	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
+	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
 	for _, bidderName := range knownAdapters {
 		if _, ok := e.adapterMap[bidderName]; !ok {
 			t.Errorf("NewExchange produced an Exchange without bidder %s", bidderName)
@@ -108,13 +108,13 @@ func TestCharacterEscape(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
 
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
-	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
+	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
 
 	// 	3) Build all the parameters e.buildBidResponse(ctx.Background(), liveA... ) needs
 	//liveAdapters []openrtb_ext.BidderName,
@@ -308,7 +308,7 @@ func TestDebugBehaviour(t *testing.T) {
 	e := new(exchange)
 
 	e.cache = &wellBehavedCache{}
-	e.me = &metricsConf.DummyMetricsEngine{}
+	e.me = &metricsConf.NilMetricsEngine{}
 	e.gDPR = gdpr.AlwaysAllow{}
 	e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	e.categoriesFetcher = categoriesFetcher
@@ -319,7 +319,7 @@ func TestDebugBehaviour(t *testing.T) {
 	for _, test := range testCases {
 
 		e.adapterMap = map[openrtb_ext.BidderName]adaptedBidder{
-			openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: test.debugData.bidderLevelDebugAllowed}),
+			openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: test.debugData.bidderLevelDebugAllowed}),
 		}
 
 		bidRequest.Test = test.in.test
@@ -463,7 +463,7 @@ func TestTwoBiddersDebugDisabledAndEnabled(t *testing.T) {
 
 	e := new(exchange)
 	e.cache = &wellBehavedCache{}
-	e.me = &metricsConf.DummyMetricsEngine{}
+	e.me = &metricsConf.NilMetricsEngine{}
 	e.gDPR = gdpr.AlwaysAllow{}
 	e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	e.categoriesFetcher = categoriesFetcher
@@ -494,8 +494,8 @@ func TestTwoBiddersDebugDisabledAndEnabled(t *testing.T) {
 		}
 
 		e.adapterMap = map[openrtb_ext.BidderName]adaptedBidder{
-			openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: testCase.bidder1DebugEnabled}),
-			openrtb_ext.BidderTelaria:  adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: testCase.bidder2DebugEnabled}),
+			openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: testCase.bidder1DebugEnabled}),
+			openrtb_ext.BidderTelaria:  adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, &config.DebugInfo{Allow: testCase.bidder2DebugEnabled}),
 		}
 		// Run test
 		outBidResponse, err := e.HoldAuction(context.Background(), auctionRequest, &debugLog)
@@ -619,7 +619,7 @@ func TestOverrideWithCustomCurrency(t *testing.T) {
 
 	e := new(exchange)
 	e.cache = &wellBehavedCache{}
-	e.me = &metricsConf.DummyMetricsEngine{}
+	e.me = &metricsConf.NilMetricsEngine{}
 	e.gDPR = gdpr.AlwaysAllow{}
 	e.currencyConverter = mockCurrencyConverter
 	e.categoriesFetcher = categoriesFetcher
@@ -649,7 +649,7 @@ func TestOverrideWithCustomCurrency(t *testing.T) {
 		}
 
 		e.adapterMap = map[openrtb_ext.BidderName]adaptedBidder{
-			openrtb_ext.BidderAppnexus: adaptBidder(oneDollarBidBidder, mockAppnexusBidService.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil),
+			openrtb_ext.BidderAppnexus: adaptBidder(oneDollarBidBidder, mockAppnexusBidService.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil),
 		}
 
 		// Set custom rates in extension
@@ -713,13 +713,13 @@ func TestAdapterCurrency(t *testing.T) {
 	// Initialize Real Exchange
 	e := exchange{
 		cache:             &wellBehavedCache{},
-		me:                &metricsConf.DummyMetricsEngine{},
+		me:                &metricsConf.NilMetricsEngine{},
 		gDPR:              gdpr.AlwaysAllow{},
 		currencyConverter: currencyConverter,
 		categoriesFetcher: nilCategoryFetcher{},
 		bidIDGenerator:    &mockBidIDGenerator{false, false},
 		adapterMap: map[openrtb_ext.BidderName]adaptedBidder{
-			openrtb_ext.BidderName("foo"): adaptBidder(mockBidder, nil, &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderName("foo"), nil),
+			openrtb_ext.BidderName("foo"): adaptBidder(mockBidder, nil, &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderName("foo"), nil),
 		},
 	}
 
@@ -1100,10 +1100,10 @@ func TestReturnCreativeEndToEnd(t *testing.T) {
 
 	e := new(exchange)
 	e.adapterMap = map[openrtb_ext.BidderName]adaptedBidder{
-		openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil),
+		openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil),
 	}
 	e.cache = &wellBehavedCache{}
-	e.me = &metricsConf.DummyMetricsEngine{}
+	e.me = &metricsConf.NilMetricsEngine{}
 	e.gDPR = gdpr.AlwaysAllow{}
 	e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	e.categoriesFetcher = categoriesFetcher
@@ -1196,13 +1196,13 @@ func TestGetBidCacheInfoEndToEnd(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 	pbc := pbc.NewClient(&http.Client{}, &cfg.CacheURL, &cfg.ExtCacheURL, testEngine)
-	e := NewExchange(adapters, pbc, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
+	e := NewExchange(adapters, pbc, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
 	// 	3) Build all the parameters e.buildBidResponse(ctx.Background(), liveA... ) needs
 	liveAdapters := []openrtb_ext.BidderName{bidderName}
 
@@ -1390,10 +1390,10 @@ func TestBidReturnsCreative(t *testing.T) {
 	}
 	e := new(exchange)
 	e.adapterMap = map[openrtb_ext.BidderName]adaptedBidder{
-		openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil),
+		openrtb_ext.BidderAppnexus: adaptBidder(bidderImpl, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil),
 	}
 	e.cache = &wellBehavedCache{}
-	e.me = &metricsConf.DummyMetricsEngine{}
+	e.me = &metricsConf.NilMetricsEngine{}
 	e.gDPR = gdpr.AlwaysAllow{}
 	e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
 
@@ -1550,13 +1550,13 @@ func TestBidResponseCurrency(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
 
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
-	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
+	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
 
 	liveAdapters := make([]openrtb_ext.BidderName, 1)
 	liveAdapters[0] = "appnexus"
@@ -1695,7 +1695,7 @@ func TestBidResponseImpExtInfo(t *testing.T) {
 	cfg := &config.Configuration{Adapters: make(map[string]config.Adapter, 1)}
 	cfg.Adapters["appnexus"] = config.Adapter{Endpoint: "http://ib.adnxs.com"}
 
-	e := NewExchange(nil, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, nil, gdpr.AlwaysAllow{}, nil, nilCategoryFetcher{}).(*exchange)
+	e := NewExchange(nil, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, nil, gdpr.AlwaysAllow{}, nil, nilCategoryFetcher{}).(*exchange)
 
 	liveAdapters := make([]openrtb_ext.BidderName, 1)
 	liveAdapters[0] = "appnexus"
@@ -1780,7 +1780,7 @@ func TestRaceIntegration(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
@@ -1794,7 +1794,7 @@ func TestRaceIntegration(t *testing.T) {
 	}
 
 	debugLog := DebugLog{}
-	ex := NewExchange(adapters, &wellBehavedCache{}, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, &nilCategoryFetcher{}).(*exchange)
+	ex := NewExchange(adapters, &wellBehavedCache{}, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, &nilCategoryFetcher{}).(*exchange)
 	_, err = ex.HoldAuction(context.Background(), auctionRequest, &debugLog)
 	if err != nil {
 		t.Errorf("HoldAuction returned unexpected error: %v", err)
@@ -1880,13 +1880,13 @@ func TestPanicRecovery(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(&http.Client{}, cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(&http.Client{}, cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
 
 	currencyConverter := currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
-	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
+	e := NewExchange(adapters, nil, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, nilCategoryFetcher{}).(*exchange)
 
 	chBids := make(chan *bidResponseWrapper, 1)
 	panicker := func(bidderRequest BidderRequest, conversions currency.Conversions) {
@@ -1947,7 +1947,7 @@ func TestPanicRecoveryHighLevel(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.DummyMetricsEngine{})
+	adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{})
 	if adaptersErr != nil {
 		t.Fatalf("Error intializing adapters: %v", adaptersErr)
 	}
@@ -1959,7 +1959,7 @@ func TestPanicRecoveryHighLevel(t *testing.T) {
 		t.Errorf("Failed to create a category Fetcher: %v", error)
 	}
 
-	e := NewExchange(adapters, &mockCache{}, cfg, map[string]usersync.Syncer{}, &metricsConf.DummyMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, categoriesFetcher).(*exchange)
+	e := NewExchange(adapters, &mockCache{}, cfg, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdpr.AlwaysAllow{}, currencyConverter, categoriesFetcher).(*exchange)
 
 	e.adapterMap[openrtb_ext.BidderBeachfront] = panicingAdapter{}
 	e.adapterMap[openrtb_ext.BidderAppnexus] = panicingAdapter{}
diff --git a/exchange/targeting_test.go b/exchange/targeting_test.go
index f38a6c02..8991a116 100644
--- a/exchange/targeting_test.go
+++ b/exchange/targeting_test.go
@@ -88,7 +88,7 @@ func runTargetingAuction(t *testing.T, mockBids map[openrtb_ext.BidderName][]*op
 
 	ex := &exchange{
 		adapterMap:        buildAdapterMap(mockBids, server.URL, server.Client()),
-		me:                &metricsConf.DummyMetricsEngine{},
+		me:                &metricsConf.NilMetricsEngine{},
 		cache:             &wellBehavedCache{},
 		cacheTime:         time.Duration(0),
 		gDPR:              gdpr.AlwaysAllow{},
@@ -143,7 +143,7 @@ func buildAdapterMap(bids map[openrtb_ext.BidderName][]*openrtb2.Bid, mockServer
 		adapterMap[bidder] = adaptBidder(&mockTargetingBidder{
 			mockServerURL: mockServerURL,
 			bids:          bids,
-		}, client, &config.Configuration{}, &metricsConfig.DummyMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
+		}, client, &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderAppnexus, nil)
 	}
 	return adapterMap
 }
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 14ebb8e9..6360fc3b 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -1936,22 +1936,39 @@ func newBidRequest(t *testing.T) *openrtb2.BidRequest {
 }
 
 func TestRandomizeList(t *testing.T) {
-	adapters := make([]openrtb_ext.BidderName, 3)
-	adapters[0] = openrtb_ext.BidderName("dummy")
-	adapters[1] = openrtb_ext.BidderName("dummy2")
-	adapters[2] = openrtb_ext.BidderName("dummy3")
-
-	randomizeList(adapters)
+	var (
+		bidder1 = openrtb_ext.BidderName("bidder1")
+		bidder2 = openrtb_ext.BidderName("bidder2")
+		bidder3 = openrtb_ext.BidderName("bidder3")
+	)
 
-	if len(adapters) != 3 {
-		t.Errorf("RandomizeList, expected a list of 3, found %d", len(adapters))
+	testCases := []struct {
+		description string
+		bidders     []openrtb_ext.BidderName
+	}{
+		{
+			description: "None",
+			bidders:     []openrtb_ext.BidderName{},
+		},
+		{
+			description: "One",
+			bidders:     []openrtb_ext.BidderName{bidder1},
+		},
+		{
+			description: "Many",
+			bidders:     []openrtb_ext.BidderName{bidder1, bidder2, bidder3},
+		},
 	}
 
-	adapters = adapters[0:1]
-	randomizeList(adapters)
+	for _, test := range testCases {
+		biddersWorkingCopy := make([]openrtb_ext.BidderName, len(test.bidders))
+		copy(biddersWorkingCopy, test.bidders)
+
+		randomizeList(biddersWorkingCopy)
 
-	if len(adapters) != 1 {
-		t.Errorf("RandomizeList, expected a list of 1, found %d", len(adapters))
+		// test all bidders are still present, ignoring order. we are testing the algorithm doesn't loose
+		// elements. we are not testing the random number generator itself.
+		assert.ElementsMatch(t, test.bidders, biddersWorkingCopy)
 	}
 }
 
diff --git a/metrics/config/metrics_test.go b/metrics/config/metrics_test.go
index 04c88867..0d6bcdb9 100644
--- a/metrics/config/metrics_test.go
+++ b/metrics/config/metrics_test.go
@@ -12,14 +12,14 @@ import (
 )
 
 // Start a simple test to insure we get valid MetricsEngines for various configurations
-func TestDummyMetricsEngine(t *testing.T) {
+func TestNilMetricsEngine(t *testing.T) {
 	cfg := mainConfig.Configuration{}
 	adapterList := make([]openrtb_ext.BidderName, 0, 2)
 	syncerKeys := []string{"keyA", "keyB"}
 	testEngine := NewMetricsEngine(&cfg, adapterList, syncerKeys)
-	_, ok := testEngine.MetricsEngine.(*DummyMetricsEngine)
+	_, ok := testEngine.MetricsEngine.(*NilMetricsEngine)
 	if !ok {
-		t.Error("Expected a DummyMetricsEngine, but didn't get it")
+		t.Error("Expected a NilMetricsEngine, but didn't get it")
 	}
 }
 
@@ -43,7 +43,7 @@ func TestMultiMetricsEngine(t *testing.T) {
 	goEngine := metrics.NewMetrics(gometrics.NewPrefixedRegistry("prebidserver."), adapterList, mainConfig.DisabledMetrics{}, nil)
 	engineList := make(MultiMetricsEngine, 2)
 	engineList[0] = goEngine
-	engineList[1] = &DummyMetricsEngine{}
+	engineList[1] = &NilMetricsEngine{}
 	var metricsEngine metrics.MetricsEngine
 	metricsEngine = &engineList
 	labels := metrics.Labels{
diff --git a/prebid_cache_client/client_test.go b/prebid_cache_client/client_test.go
index 1ba30a6f..60237bbb 100644
--- a/prebid_cache_client/client_test.go
+++ b/prebid_cache_client/client_test.go
@@ -257,7 +257,7 @@ func TestStripCacheHostAndPath(t *testing.T) {
 		},
 	}
 	for _, test := range testInput {
-		cacheClient := NewClient(&http.Client{}, &inCacheURL, &test.inExtCacheURL, &metricsConf.DummyMetricsEngine{})
+		cacheClient := NewClient(&http.Client{}, &inCacheURL, &test.inExtCacheURL, &metricsConf.NilMetricsEngine{})
 		scheme, host, path := cacheClient.GetExtCacheData()
 
 		assert.Equal(t, test.expectedScheme, scheme)
diff --git a/stored_requests/events/events_test.go b/stored_requests/events/events_test.go
index f3483705..c943dd69 100644
--- a/stored_requests/events/events_test.go
+++ b/stored_requests/events/events_test.go
@@ -12,7 +12,7 @@ import (
 )
 
 func TestListen(t *testing.T) {
-	ep := &dummyProducer{
+	ep := &fakeProducer{
 		saves:         make(chan Save),
 		invalidations: make(chan Invalidation),
 	}
@@ -81,15 +81,15 @@ func TestListen(t *testing.T) {
 	}
 }
 
-type dummyProducer struct {
+type fakeProducer struct {
 	saves         chan Save
 	invalidations chan Invalidation
 }
 
-func (p *dummyProducer) Saves() <-chan Save {
+func (p *fakeProducer) Saves() <-chan Save {
 	return p.saves
 }
 
-func (p *dummyProducer) Invalidations() <-chan Invalidation {
+func (p *fakeProducer) Invalidations() <-chan Invalidation {
 	return p.invalidations
 }