Repository: prebid/prebid-server
Pull request #2995 (2023-08-01 10:55:30)

minor refactor in HoldAuction 
PR includes following refactor in HoldAuction and its related code:
- [buildBidResponse: remove unused err var](https://github.com/prebid/prebid-server/commit/e12764ff7b530354211e91ee62ee80201bed3599)
- [HoldAuction: set seatNonBid only if has no error](https://github.com/prebid/prebid-server/commit/647ccfda38d8c3c2e508dd26b2e011ba5c1af474)


Patch:
diff --git a/adapters/appnexus/appnexus.go b/adapters/appnexus/appnexus.go
index 93a0bf95..ddba6a58 100644
--- a/adapters/appnexus/appnexus.go
+++ b/adapters/appnexus/appnexus.go
@@ -13,6 +13,8 @@ import (
 	"github.com/prebid/openrtb/v19/adcom1"
 	"github.com/prebid/openrtb/v19/openrtb2"
 	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/util/maputil"
+	"github.com/prebid/prebid-server/util/ptrutil"
 	"github.com/prebid/prebid-server/util/randomutil"
 
 	"github.com/prebid/prebid-server/adapters"
@@ -22,8 +24,8 @@ import (
 )
 
 const (
-	defaultPlatformID int = 5
-	maxImpsPerReq         = 10
+	defaultPlatformID = 5
+	maxImpsPerReq     = 10
 )
 
 type adapter struct {
@@ -65,7 +67,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 	var (
 		shouldGenerateAdPodId *bool
 		uniqueMemberID        string
-		errs                  = make([]error, 0, len(request.Imp))
+		errs                  []error
 	)
 
 	validImps := []openrtb2.Imp{}
@@ -112,7 +114,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 	}
 
 	requestURI := a.uri
-
 	if uniqueMemberID != "" {
 		requestURI = appendMemberId(requestURI, uniqueMemberID)
 	}
@@ -125,10 +126,20 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 		isVIDEO = 1
 	}
 
-	reqExt, err := a.getRequestExt(request.Ext, isAMP, isVIDEO)
+	reqExt, err := getRequestExt(request.Ext)
+	if err != nil {
+		return nil, append(errs, err)
+	}
+
+	reqExtAppnexus, err := a.getAppnexusExt(reqExt, isAMP, isVIDEO)
 	if err != nil {
 		return nil, append(errs, err)
 	}
+
+	if err := moveSupplyChain(request, reqExt); err != nil {
+		return nil, append(errs, err)
+	}
+
 	// For long form requests if adpodId feature enabled, adpod_id must be sent downstream.
 	// Adpod id is a unique identifier for pod
 	// All impressions in the same pod must have the same pod id in request extension
@@ -136,11 +147,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 	// If impressions number per pod is more than maxImpsPerReq - divide those imps to several requests but keep pod id the same
 	// If  adpodId feature disabled and impressions number per pod is more than maxImpsPerReq  - divide those imps to several requests but do not include ad pod id
 	if isVIDEO == 1 && *shouldGenerateAdPodId {
-		requests, errors := a.buildAdPodRequests(request.Imp, request, reqExt, requestURI.String())
+		requests, errors := a.buildAdPodRequests(request.Imp, request, reqExt, reqExtAppnexus, requestURI.String())
 		return requests, append(errs, errors...)
 	}
 
-	requests, errors := splitRequests(request.Imp, request, reqExt, requestURI.String())
+	requests, errors := splitRequests(request.Imp, request, reqExt, reqExtAppnexus, requestURI.String())
 	return requests, append(errs, errors...)
 }
 
@@ -200,25 +211,43 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest
 	return bidderResponse, errs
 }
 
-func (a *adapter) getRequestExt(ext json.RawMessage, isAMP int, isVIDEO int) (bidReqExt, error) {
-	var reqExt bidReqExt
+func getRequestExt(ext json.RawMessage) (map[string]json.RawMessage, error) {
+	extMap := make(map[string]json.RawMessage)
+
 	if len(ext) > 0 {
-		if err := json.Unmarshal(ext, &reqExt); err != nil {
-			return bidReqExt{}, err
+		if err := json.Unmarshal(ext, &extMap); err != nil {
+			return nil, err
 		}
 	}
-	if reqExt.Appnexus == nil {
-		reqExt.Appnexus = &bidReqExtAppnexus{}
+
+	return extMap, nil
+}
+
+func (a *adapter) getAppnexusExt(extMap map[string]json.RawMessage, isAMP int, isVIDEO int) (bidReqExtAppnexus, error) {
+	var appnexusExt bidReqExtAppnexus
+
+	if appnexusExtJson, exists := extMap["appnexus"]; exists && len(appnexusExtJson) > 0 {
+		if err := json.Unmarshal(appnexusExtJson, &appnexusExt); err != nil {
+			return appnexusExt, err
+		}
 	}
-	includeBrandCategory := reqExt.Prebid.Targeting != nil && reqExt.Prebid.Targeting.IncludeBrandCategory != nil
-	if includeBrandCategory {
-		reqExt.Appnexus.BrandCategoryUniqueness = &includeBrandCategory
-		reqExt.Appnexus.IncludeBrandCategory = &includeBrandCategory
+
+	if prebidJson, exists := extMap["prebid"]; exists {
+		_, valueType, _, err := jsonparser.Get(prebidJson, "targeting", "includebrandcategory")
+		if err != nil && !errors.Is(err, jsonparser.KeyPathNotFoundError) {
+			return appnexusExt, err
+		}
+
+		if valueType == jsonparser.Object {
+			appnexusExt.BrandCategoryUniqueness = ptrutil.ToPtr(true)
+			appnexusExt.IncludeBrandCategory = ptrutil.ToPtr(true)
+		}
 	}
-	reqExt.Appnexus.IsAMP = isAMP
-	reqExt.Appnexus.HeaderBiddingSource = a.hbSource + isVIDEO
 
-	return reqExt, nil
+	appnexusExt.IsAMP = isAMP
+	appnexusExt.HeaderBiddingSource = a.hbSource + isVIDEO
+
+	return appnexusExt, nil
 }
 
 func validateAndBuildAppNexusExt(imp *openrtb2.Imp) (openrtb_ext.ExtImpAppnexus, error) {
@@ -266,7 +295,7 @@ func groupByPods(imps []openrtb2.Imp) map[string]([]openrtb2.Imp) {
 	return podImps
 }
 
-func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExtension bidReqExt, uri string) ([]*adapters.RequestData, []error) {
+func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExt map[string]json.RawMessage, requestExtAppnexus bidReqExtAppnexus, uri string) ([]*adapters.RequestData, []error) {
 	var errs []error
 	// Initial capacity for future array of requests, memory optimization.
 	// Let's say there are 35 impressions and limit impressions per request equals to 10.
@@ -281,14 +310,20 @@ func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExt
 	headers.Add("Content-Type", "application/json;charset=utf-8")
 	headers.Add("Accept", "application/json")
 
-	var err error
-	request.Ext, err = json.Marshal(requestExtension)
+	appnexusExtJson, err := json.Marshal(requestExtAppnexus)
 	if err != nil {
 		errs = append(errs, err)
 	}
 
-	for impsLeft {
+	requestExtClone := maputil.Clone(requestExt)
+	requestExtClone["appnexus"] = appnexusExtJson
 
+	request.Ext, err = json.Marshal(requestExtClone)
+	if err != nil {
+		errs = append(errs, err)
+	}
+
+	for impsLeft {
 		endInd := startInd + maxImpsPerReq
 		if endInd >= len(imps) {
 			endInd = len(imps)
@@ -327,9 +362,11 @@ func buildRequestImp(imp *openrtb2.Imp, appnexusExt *openrtb_ext.ExtImpAppnexus,
 	if appnexusExt.InvCode != "" {
 		imp.TagID = appnexusExt.InvCode
 	}
+
 	if imp.BidFloor <= 0 && appnexusExt.Reserve > 0 {
 		imp.BidFloor = appnexusExt.Reserve // This will be broken for non-USD currency.
 	}
+
 	if imp.Banner != nil {
 		bannerCopy := *imp.Banner
 		if appnexusExt.Position == "above" {
@@ -358,7 +395,7 @@ func buildRequestImp(imp *openrtb2.Imp, appnexusExt *openrtb_ext.ExtImpAppnexus,
 		UsePmtRule:        appnexusExt.UsePaymentRule,
 		PrivateSizes:      appnexusExt.PrivateSizes,
 		ExtInvCode:        appnexusExt.ExtInvCode,
-		ExternalImpId:     appnexusExt.ExternalImpId,
+		ExternalImpID:     appnexusExt.ExternalImpId,
 	}}
 
 	var err error
@@ -413,14 +450,49 @@ func buildDisplayManageVer(req *openrtb2.BidRequest) string {
 	return fmt.Sprintf("%s-%s", source, version)
 }
 
-func (a *adapter) buildAdPodRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExtension bidReqExt, uri string) ([]*adapters.RequestData, []error) {
+// moveSupplyChain moves the supply chain object from source.ext.schain to ext.schain.
+func moveSupplyChain(request *openrtb2.BidRequest, extMap map[string]json.RawMessage) error {
+	if request == nil || request.Source == nil || len(request.Source.Ext) == 0 {
+		return nil
+	}
+
+	sourceExtMap := make(map[string]json.RawMessage)
+	if err := json.Unmarshal(request.Source.Ext, &sourceExtMap); err != nil {
+		return err
+	}
+
+	schainJson, exists := sourceExtMap["schain"]
+	if !exists {
+		return nil
+	}
+
+	delete(sourceExtMap, "schain")
+
+	request.Source = ptrutil.Clone(request.Source)
+
+	if len(sourceExtMap) > 0 {
+		ext, err := json.Marshal(sourceExtMap)
+		if err != nil {
+			return err
+		}
+		request.Source.Ext = ext
+	} else {
+		request.Source.Ext = nil
+	}
+
+	extMap["schain"] = schainJson
+
+	return nil
+}
+
+func (a *adapter) buildAdPodRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExt map[string]json.RawMessage, requestExtAppnexus bidReqExtAppnexus, uri string) ([]*adapters.RequestData, []error) {
 	var errs []error
 	podImps := groupByPods(imps)
 	requests := make([]*adapters.RequestData, 0, len(podImps))
 	for _, podImps := range podImps {
-		requestExtension.Appnexus.AdPodId = fmt.Sprint(a.randomGenerator.GenerateInt63())
+		requestExtAppnexus.AdPodID = fmt.Sprint(a.randomGenerator.GenerateInt63())
 
-		reqs, errors := splitRequests(podImps, request, requestExtension, uri)
+		reqs, errors := splitRequests(podImps, request, requestExt, requestExtAppnexus, uri)
 		requests = append(requests, reqs...)
 		errs = append(errs, errors...)
 	}
diff --git a/adapters/appnexus/models.go b/adapters/appnexus/models.go
index 826451b4..c70f89fa 100644
--- a/adapters/appnexus/models.go
+++ b/adapters/appnexus/models.go
@@ -2,8 +2,6 @@ package appnexus
 
 import (
 	"encoding/json"
-
-	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
 type impExtAppnexus struct {
@@ -13,7 +11,7 @@ type impExtAppnexus struct {
 	UsePmtRule        *bool           `json:"use_pmt_rule,omitempty"`
 	PrivateSizes      json.RawMessage `json:"private_sizes,omitempty"`
 	ExtInvCode        string          `json:"ext_inv_code,omitempty"`
-	ExternalImpId     string          `json:"external_imp_id,omitempty"`
+	ExternalImpID     string          `json:"external_imp_id,omitempty"`
 }
 
 type impExt struct {
@@ -45,11 +43,5 @@ type bidReqExtAppnexus struct {
 	BrandCategoryUniqueness *bool  `json:"brand_category_uniqueness,omitempty"`
 	IsAMP                   int    `json:"is_amp,omitempty"`
 	HeaderBiddingSource     int    `json:"hb_source,omitempty"`
-	AdPodId                 string `json:"adpod_id,omitempty"`
-}
-
-// Full request extension including appnexus extension object
-type bidReqExt struct {
-	openrtb_ext.ExtRequest
-	Appnexus *bidReqExtAppnexus `json:"appnexus,omitempty"`
+	AdPodID                 string `json:"adpod_id,omitempty"`
 }
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 7ad15200..70d92c08 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -490,17 +490,14 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
 	e.bidValidationEnforcement.SetBannerCreativeMaxSize(r.Account.Validations)
 
 	// Build the response
-	bidResponse, err := e.buildBidResponse(ctx, liveAdapters, adapterBids, r.BidRequestWrapper.BidRequest, adapterExtra, auc, bidResponseExt, cacheInstructions.returnCreative, r.ImpExtInfoMap, r.PubID, errs)
-
+	bidResponse := e.buildBidResponse(ctx, liveAdapters, adapterBids, r.BidRequestWrapper.BidRequest, adapterExtra, auc, bidResponseExt, cacheInstructions.returnCreative, r.ImpExtInfoMap, r.PubID, errs)
 	bidResponse = adservertargeting.Apply(r.BidRequestWrapper, r.ResolvedBidRequest, bidResponse, r.QueryParams, bidResponseExt, r.Account.TruncateTargetAttribute)
 
 	bidResponse.Ext, err = encodeBidResponseExt(bidResponseExt)
-
-	bidResponseExt = setSeatNonBid(bidResponseExt, seatNonBids)
-
 	if err != nil {
 		return nil, err
 	}
+	bidResponseExt = setSeatNonBid(bidResponseExt, seatNonBids)
 
 	return &AuctionResponse{
 		BidResponse:    bidResponse,
@@ -880,9 +877,8 @@ func errsToBidderWarnings(errs []error) []openrtb_ext.ExtBidderMessage {
 }
 
 // This piece takes all the bids supplied by the adapters and crafts an openRTB response to send back to the requester
-func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ext.BidderName, adapterSeatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, bidRequest *openrtb2.BidRequest, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, bidResponseExt *openrtb_ext.ExtBidResponse, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, pubID string, errList []error) (*openrtb2.BidResponse, error) {
+func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ext.BidderName, adapterSeatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, bidRequest *openrtb2.BidRequest, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, bidResponseExt *openrtb_ext.ExtBidResponse, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, pubID string, errList []error) *openrtb2.BidResponse {
 	bidResponse := new(openrtb2.BidResponse)
-	var err error
 
 	bidResponse.ID = bidRequest.ID
 	if len(liveAdapters) == 0 {
@@ -903,7 +899,7 @@ func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_
 	}
 	bidResponse.SeatBid = seatBids
 
-	return bidResponse, err
+	return bidResponse
 }
 
 func encodeBidResponseExt(bidResponseExt *openrtb_ext.ExtBidResponse) ([]byte, error) {


Test patch:
diff --git a/adapters/appnexus/appnexus_test.go b/adapters/appnexus/appnexus_test.go
index e6ba0109..bb04b61b 100644
--- a/adapters/appnexus/appnexus_test.go
+++ b/adapters/appnexus/appnexus_test.go
@@ -8,6 +8,7 @@ import (
 	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/openrtb_ext"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestJsonSamples(t *testing.T) {
@@ -26,7 +27,8 @@ func TestJsonSamples(t *testing.T) {
 
 func TestAppendMemberID(t *testing.T) {
 	uri, err := url.Parse("http://ib.adnxs.com/openrtb2?query_param=true")
-	assert.NoError(t, err, "Failed to parse URI with query string")
+	require.NoError(t, err, "Failed to parse URI with query string")
+
 	uriWithMember := appendMemberId(*uri, "102")
 	expected := "http://ib.adnxs.com/openrtb2?member_id=102&query_param=true"
 	assert.Equal(t, expected, uriWithMember.String(), "Failed to append member id to URI with query string")
@@ -37,11 +39,10 @@ func TestBuilderWithPlatformID(t *testing.T) {
 		Endpoint: "http://ib.adnxs.com/openrtb2", PlatformID: "3"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
 
 	assert.NoError(t, buildErr)
-	assert.NotNil(t, bidder)
+	require.NotNil(t, bidder)
 	assert.Equal(t, 3, (*bidder.(*adapter)).hbSource)
 }
 
-// fakerandomNumberGenerator
 type FakeRandomNumberGenerator struct {
 	Number int64
 }
diff --git a/adapters/appnexus/appnexustest/amp/simple-banner.json b/adapters/appnexus/appnexustest/amp/simple-banner.json
index 54e6a143..4ed3403d 100644
--- a/adapters/appnexus/appnexustest/amp/simple-banner.json
+++ b/adapters/appnexus/appnexustest/amp/simple-banner.json
@@ -34,8 +34,6 @@
             "appnexus": {
               "is_amp": 1,
               "hb_source": 5
-            },
-            "prebid": {
             }
           },
           "id": "test-request-id",
diff --git a/adapters/appnexus/appnexustest/amp/simple-video.json b/adapters/appnexus/appnexustest/amp/simple-video.json
index c9744831..623085e7 100644
--- a/adapters/appnexus/appnexustest/amp/simple-video.json
+++ b/adapters/appnexus/appnexustest/amp/simple-video.json
@@ -30,8 +30,6 @@
 				"appnexus": {
 					"is_amp": 1,
 					"hb_source": 5
-				},
-				"prebid": {
 				}
 			},
 			"id": "test-request-id",
diff --git a/adapters/appnexus/appnexustest/exemplary/dynamic-keywords-params.json b/adapters/appnexus/appnexustest/exemplary/dynamic-keywords-params.json
index 869c32d8..d0af71e6 100644
--- a/adapters/appnexus/appnexustest/exemplary/dynamic-keywords-params.json
+++ b/adapters/appnexus/appnexustest/exemplary/dynamic-keywords-params.json
@@ -41,8 +41,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/exemplary/native-1.1.json b/adapters/appnexus/appnexustest/exemplary/native-1.1.json
index 189304fd..b40543f1 100644
--- a/adapters/appnexus/appnexustest/exemplary/native-1.1.json
+++ b/adapters/appnexus/appnexustest/exemplary/native-1.1.json
@@ -51,8 +51,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "site": {
             "domain": "prebid.org",
diff --git a/adapters/appnexus/appnexustest/exemplary/optional-params.json b/adapters/appnexus/appnexustest/exemplary/optional-params.json
index e105d6e1..01af8252 100644
--- a/adapters/appnexus/appnexustest/exemplary/optional-params.json
+++ b/adapters/appnexus/appnexustest/exemplary/optional-params.json
@@ -46,8 +46,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/exemplary/schain-24-other-ext.json b/adapters/appnexus/appnexustest/exemplary/schain-24-other-ext.json
new file mode 100644
index 00000000..e5a258e7
--- /dev/null
+++ b/adapters/appnexus/appnexustest/exemplary/schain-24-other-ext.json
@@ -0,0 +1,193 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "app": {
+            "ext": {
+                "prebid": {
+                    "source": "source",
+                    "version": "version"
+                }
+            }
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 1,
+                        "position": "above"
+                    }
+                }
+            }
+        ],
+        "ext": {
+            "schain": {
+                "complete": 0,
+                "nodes": [
+                    {
+                        "asi": "pbshostcompany.com",
+                        "sid": "00001",
+                        "rid": "BidRequest",
+                        "hp": 1
+                    }
+                ],
+                "ver": "1.0"
+            },
+            "otherRequest": "value"
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://ib.adnxs.com/openrtb2",
+                "body": {
+                    "id": "test-request-id",
+                    "app": {
+                        "ext": {
+                            "prebid": {
+                                "source": "source",
+                                "version": "version"
+                            }
+                        }
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "hb_source": 5
+                        },
+                        "schain": {
+                            "complete": 0,
+                            "nodes": [
+                                {
+                                    "asi": "pbshostcompany.com",
+                                    "sid": "00001",
+                                    "rid": "BidRequest",
+                                    "hp": 1
+                                }
+                            ],
+                            "ver": "1.0"
+                        },
+                        "otherRequest": "value"
+                    },
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "pos": 1,
+                                "h": 250
+                            },
+                            "displaymanagerver": "source-version",
+                            "ext": {
+                                "appnexus": {
+                                    "placement_id": 1
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "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,
+                                            "brand_category_id": 1,
+                                            "auction_id": 8189378542222915032,
+                                            "bid_ad_type": 0,
+                                            "bidder_id": 2,
+                                            "ranking_price": 0.000000,
+                                            "deal_priority": 5
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "appnexus.com"
+                        ],
+                        "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "cat": [
+                            "IAB20-3"
+                        ],
+                        "ext": {
+                            "appnexus": {
+                                "brand_id": 1,
+                                "brand_category_id": 1,
+                                "auction_id": 8189378542222915032,
+                                "bid_ad_type": 0,
+                                "bidder_id": 2,
+                                "ranking_price": 0.000000,
+                                "deal_priority": 5
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/appnexus/appnexustest/exemplary/schain-24.json b/adapters/appnexus/appnexustest/exemplary/schain-24.json
new file mode 100644
index 00000000..d8f26d10
--- /dev/null
+++ b/adapters/appnexus/appnexustest/exemplary/schain-24.json
@@ -0,0 +1,191 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "app": {
+            "ext": {
+                "prebid": {
+                    "source": "source",
+                    "version": "version"
+                }
+            }
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 1,
+                        "position": "above"
+                    }
+                }
+            }
+        ],
+        "ext": {
+            "schain": {
+                "complete": 0,
+                "nodes": [
+                    {
+                        "asi": "pbshostcompany.com",
+                        "sid": "00001",
+                        "rid": "BidRequest",
+                        "hp": 1
+                    }
+                ],
+                "ver": "1.0"
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://ib.adnxs.com/openrtb2",
+                "body": {
+                    "id": "test-request-id",
+                    "app": {
+                        "ext": {
+                            "prebid": {
+                                "source": "source",
+                                "version": "version"
+                            }
+                        }
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "hb_source": 5
+                        },
+                        "schain": {
+                            "complete": 0,
+                            "nodes": [
+                                {
+                                    "asi": "pbshostcompany.com",
+                                    "sid": "00001",
+                                    "rid": "BidRequest",
+                                    "hp": 1
+                                }
+                            ],
+                            "ver": "1.0"
+                        }
+                    },
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "pos": 1,
+                                "h": 250
+                            },
+                            "displaymanagerver": "source-version",
+                            "ext": {
+                                "appnexus": {
+                                    "placement_id": 1
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "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,
+                                            "brand_category_id": 1,
+                                            "auction_id": 8189378542222915032,
+                                            "bid_ad_type": 0,
+                                            "bidder_id": 2,
+                                            "ranking_price": 0.000000,
+                                            "deal_priority": 5
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "appnexus.com"
+                        ],
+                        "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "cat": [
+                            "IAB20-3"
+                        ],
+                        "ext": {
+                            "appnexus": {
+                                "brand_id": 1,
+                                "brand_category_id": 1,
+                                "auction_id": 8189378542222915032,
+                                "bid_ad_type": 0,
+                                "bidder_id": 2,
+                                "ranking_price": 0.000000,
+                                "deal_priority": 5
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/appnexus/appnexustest/exemplary/schain-25-other-ext.json b/adapters/appnexus/appnexustest/exemplary/schain-25-other-ext.json
new file mode 100644
index 00000000..19b9f1db
--- /dev/null
+++ b/adapters/appnexus/appnexustest/exemplary/schain-25-other-ext.json
@@ -0,0 +1,203 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "app": {
+            "ext": {
+                "prebid": {
+                    "source": "source",
+                    "version": "version"
+                }
+            }
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 1,
+                        "position": "above"
+                    }
+                }
+            }
+        ],
+        "source": {
+            "ext": {
+                "schain": {
+                    "complete": 0,
+                    "nodes": [
+                        {
+                            "asi": "pbshostcompany.com",
+                            "sid": "00001",
+                            "rid": "BidRequest",
+                            "hp": 1
+                        }
+                    ],
+                    "ver": "1.0"
+                },
+                "otherSource": "value"
+            }
+        },
+        "ext": {
+            "otherRequest": "value"
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://ib.adnxs.com/openrtb2",
+                "body": {
+                    "id": "test-request-id",
+                    "app": {
+                        "ext": {
+                            "prebid": {
+                                "source": "source",
+                                "version": "version"
+                            }
+                        }
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "hb_source": 5
+                        },
+                        "schain": {
+                            "complete": 0,
+                            "nodes": [
+                                {
+                                    "asi": "pbshostcompany.com",
+                                    "sid": "00001",
+                                    "rid": "BidRequest",
+                                    "hp": 1
+                                }
+                            ],
+                            "ver": "1.0"
+                        },
+                        "otherRequest": "value"
+                    },
+                    "source": {
+                        "ext": {
+                            "otherSource": "value"
+                        }
+                    },
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "pos": 1,
+                                "h": 250
+                            },
+                            "displaymanagerver": "source-version",
+                            "ext": {
+                                "appnexus": {
+                                    "placement_id": 1
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "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,
+                                            "brand_category_id": 1,
+                                            "auction_id": 8189378542222915032,
+                                            "bid_ad_type": 0,
+                                            "bidder_id": 2,
+                                            "ranking_price": 0.000000,
+                                            "deal_priority": 5
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "appnexus.com"
+                        ],
+                        "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "cat": [
+                            "IAB20-3"
+                        ],
+                        "ext": {
+                            "appnexus": {
+                                "brand_id": 1,
+                                "brand_category_id": 1,
+                                "auction_id": 8189378542222915032,
+                                "bid_ad_type": 0,
+                                "bidder_id": 2,
+                                "ranking_price": 0.000000,
+                                "deal_priority": 5
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/appnexus/appnexustest/exemplary/schain-25.json b/adapters/appnexus/appnexustest/exemplary/schain-25.json
new file mode 100644
index 00000000..8ff11b01
--- /dev/null
+++ b/adapters/appnexus/appnexustest/exemplary/schain-25.json
@@ -0,0 +1,194 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "app": {
+            "ext": {
+                "prebid": {
+                    "source": "source",
+                    "version": "version"
+                }
+            }
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 1,
+                        "position": "above"
+                    }
+                }
+            }
+        ],
+        "source": {
+            "ext": {
+                "schain": {
+                    "complete": 0,
+                    "nodes": [
+                        {
+                            "asi": "pbshostcompany.com",
+                            "sid": "00001",
+                            "rid": "BidRequest",
+                            "hp": 1
+                        }
+                    ],
+                    "ver": "1.0"
+                }
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://ib.adnxs.com/openrtb2",
+                "body": {
+                    "id": "test-request-id",
+                    "app": {
+                        "ext": {
+                            "prebid": {
+                                "source": "source",
+                                "version": "version"
+                            }
+                        }
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "hb_source": 5
+                        },
+                        "schain": {
+                            "complete": 0,
+                            "nodes": [
+                                {
+                                    "asi": "pbshostcompany.com",
+                                    "sid": "00001",
+                                    "rid": "BidRequest",
+                                    "hp": 1
+                                }
+                            ],
+                            "ver": "1.0"
+                        }
+                    },
+                    "source": {},
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "pos": 1,
+                                "h": 250
+                            },
+                            "displaymanagerver": "source-version",
+                            "ext": {
+                                "appnexus": {
+                                    "placement_id": 1
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "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,
+                                            "brand_category_id": 1,
+                                            "auction_id": 8189378542222915032,
+                                            "bid_ad_type": 0,
+                                            "bidder_id": 2,
+                                            "ranking_price": 0.000000,
+                                            "deal_priority": 5
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "appnexus.com"
+                        ],
+                        "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "cat": [
+                            "IAB20-3"
+                        ],
+                        "ext": {
+                            "appnexus": {
+                                "brand_id": 1,
+                                "brand_category_id": 1,
+                                "auction_id": 8189378542222915032,
+                                "bid_ad_type": 0,
+                                "bidder_id": 2,
+                                "ranking_price": 0.000000,
+                                "deal_priority": 5
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/appnexus/appnexustest/exemplary/simple-banner-foreign-currency.json b/adapters/appnexus/appnexustest/exemplary/simple-banner-foreign-currency.json
index b46c6f5f..52112419 100644
--- a/adapters/appnexus/appnexustest/exemplary/simple-banner-foreign-currency.json
+++ b/adapters/appnexus/appnexustest/exemplary/simple-banner-foreign-currency.json
@@ -34,8 +34,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/exemplary/simple-banner.json b/adapters/appnexus/appnexustest/exemplary/simple-banner.json
index ec769abd..24deea82 100644
--- a/adapters/appnexus/appnexustest/exemplary/simple-banner.json
+++ b/adapters/appnexus/appnexustest/exemplary/simple-banner.json
@@ -51,8 +51,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/exemplary/simple-video.json b/adapters/appnexus/appnexustest/exemplary/simple-video.json
index a127e2a0..beb63010 100644
--- a/adapters/appnexus/appnexustest/exemplary/simple-video.json
+++ b/adapters/appnexus/appnexustest/exemplary/simple-video.json
@@ -30,8 +30,7 @@
 			"ext": {
 				"appnexus": {
 				  "hb_source": 5
-				},
-				"prebid": {}
+				}
 			  },
 			"imp": [
 			  {
diff --git a/adapters/appnexus/appnexustest/exemplary/string-keywords-params.json b/adapters/appnexus/appnexustest/exemplary/string-keywords-params.json
index f43c47fe..a6d8d95e 100644
--- a/adapters/appnexus/appnexustest/exemplary/string-keywords-params.json
+++ b/adapters/appnexus/appnexustest/exemplary/string-keywords-params.json
@@ -41,8 +41,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json b/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json
index 257905c8..a65595e1 100644
--- a/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json
+++ b/adapters/appnexus/appnexustest/exemplary/video-invalid-category.json
@@ -30,8 +30,7 @@
 			"ext": {
 				"appnexus": {
 				  "hb_source": 5
-				},
-				"prebid": {}
+				}
 			},
 			"imp": [
 			  {
diff --git a/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json b/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json
index c6ad330e..ebfa1f23 100644
--- a/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json
+++ b/adapters/appnexus/appnexustest/supplemental/displaymanager-test.json
@@ -50,8 +50,7 @@
               "ext": {
                 "appnexus": {
                   "hb_source": 5
-                },
-                "prebid": {}
+                }
               },
               "imp": [
               {
diff --git a/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json b/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json
index 685a908b..c66f8973 100644
--- a/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json
+++ b/adapters/appnexus/appnexustest/supplemental/explicit-dimensions.json
@@ -31,8 +31,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/supplemental/invalid-bid-type.json b/adapters/appnexus/appnexustest/supplemental/invalid-bid-type.json
index 6c7f1633..a66f69e3 100644
--- a/adapters/appnexus/appnexustest/supplemental/invalid-bid-type.json
+++ b/adapters/appnexus/appnexustest/supplemental/invalid-bid-type.json
@@ -51,8 +51,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/supplemental/legacy-params.json b/adapters/appnexus/appnexustest/supplemental/legacy-params.json
index 82031145..15a4c545 100644
--- a/adapters/appnexus/appnexustest/supplemental/legacy-params.json
+++ b/adapters/appnexus/appnexustest/supplemental/legacy-params.json
@@ -37,8 +37,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/supplemental/multi-bid.json b/adapters/appnexus/appnexustest/supplemental/multi-bid.json
index 9e63bdce..664244a9 100644
--- a/adapters/appnexus/appnexustest/supplemental/multi-bid.json
+++ b/adapters/appnexus/appnexustest/supplemental/multi-bid.json
@@ -34,8 +34,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/supplemental/placement-id-as-string-test.json b/adapters/appnexus/appnexustest/supplemental/placement-id-as-string-test.json
index 1d28983b..b1e0401e 100644
--- a/adapters/appnexus/appnexustest/supplemental/placement-id-as-string-test.json
+++ b/adapters/appnexus/appnexustest/supplemental/placement-id-as-string-test.json
@@ -51,8 +51,7 @@
             "ext": {
               "appnexus": {
                 "hb_source": 5
-              },
-              "prebid": {}
+              }
             },
             "site": {
               "domain": "prebid.org",
diff --git a/adapters/appnexus/appnexustest/supplemental/request-ext-appnexus-existing.json b/adapters/appnexus/appnexustest/supplemental/request-ext-appnexus-existing.json
new file mode 100644
index 00000000..0f153117
--- /dev/null
+++ b/adapters/appnexus/appnexustest/supplemental/request-ext-appnexus-existing.json
@@ -0,0 +1,171 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "app": {
+            "ext": {
+                "prebid": {
+                    "source": "source",
+                    "version": "version"
+                }
+            }
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 1,
+                        "position": "above"
+                    }
+                }
+            }
+        ],
+        "ext": {
+            "appnexus": {
+                "adpod_id": "42"
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://ib.adnxs.com/openrtb2",
+                "body": {
+                    "id": "test-request-id",
+                    "app": {
+                        "ext": {
+                            "prebid": {
+                                "source": "source",
+                                "version": "version"
+                            }
+                        }
+                    },
+                    "ext": {
+                        "appnexus": {
+                            "hb_source": 5,
+                            "adpod_id": "42"
+                        }
+                    },
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "pos": 1,
+                                "h": 250
+                            },
+                            "displaymanagerver": "source-version",
+                            "ext": {
+                                "appnexus": {
+                                    "placement_id": 1
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "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,
+                                            "brand_category_id": 1,
+                                            "auction_id": 8189378542222915032,
+                                            "bid_ad_type": 0,
+                                            "bidder_id": 2,
+                                            "ranking_price": 0.000000,
+                                            "deal_priority": 5
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "appnexus.com"
+                        ],
+                        "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "cat": [
+                            "IAB20-3"
+                        ],
+                        "ext": {
+                            "appnexus": {
+                                "brand_id": 1,
+                                "brand_category_id": 1,
+                                "auction_id": 8189378542222915032,
+                                "bid_ad_type": 0,
+                                "bidder_id": 2,
+                                "ranking_price": 0.000000,
+                                "deal_priority": 5
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/appnexus/appnexustest/supplemental/reserve-ignored.json b/adapters/appnexus/appnexustest/supplemental/reserve-ignored.json
index 84e2b484..e9df5038 100644
--- a/adapters/appnexus/appnexustest/supplemental/reserve-ignored.json
+++ b/adapters/appnexus/appnexustest/supplemental/reserve-ignored.json
@@ -36,8 +36,7 @@
             "ext": {
               "appnexus": {
                 "hb_source": 5
-              },
-              "prebid": {}
+              }
             },
             "imp": [
               {
diff --git a/adapters/appnexus/appnexustest/supplemental/reserve-test.json b/adapters/appnexus/appnexustest/supplemental/reserve-test.json
index f5c6dfce..df861897 100644
--- a/adapters/appnexus/appnexustest/supplemental/reserve-test.json
+++ b/adapters/appnexus/appnexustest/supplemental/reserve-test.json
@@ -35,8 +35,7 @@
             "ext": {
               "appnexus": {
                 "hb_source": 5
-              },
-              "prebid": {}
+              }
             },
             "imp": [
               {
diff --git a/adapters/appnexus/appnexustest/supplemental/status-400.json b/adapters/appnexus/appnexustest/supplemental/status-400.json
index dc889012..58c7a465 100644
--- a/adapters/appnexus/appnexustest/supplemental/status-400.json
+++ b/adapters/appnexus/appnexustest/supplemental/status-400.json
@@ -35,8 +35,7 @@
           "ext": {
             "appnexus": {
               "hb_source": 5
-            },
-            "prebid": {}
+            }
           },
           "imp": [
             {
diff --git a/adapters/appnexus/appnexustest/supplemental/usePmtRule-test.json b/adapters/appnexus/appnexustest/supplemental/usePmtRule-test.json
index 64e51927..2d3f307a 100644
--- a/adapters/appnexus/appnexustest/supplemental/usePmtRule-test.json
+++ b/adapters/appnexus/appnexustest/supplemental/usePmtRule-test.json
@@ -63,8 +63,7 @@
             "ext": {
               "appnexus": {
                 "hb_source": 5
-              },
-              "prebid": {}
+              }
             },
             "imp": [
               {
diff --git a/adapters/appnexus/appnexustest/video/video-brand-category.json b/adapters/appnexus/appnexustest/video/video-brand-category.json
new file mode 100644
index 00000000..1671b971
--- /dev/null
+++ b/adapters/appnexus/appnexustest/video/video-brand-category.json
@@ -0,0 +1,179 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "minduration": 15,
+                    "maxduration": 30,
+                    "protocols": [
+                        2,
+                        3,
+                        5,
+                        6,
+                        7,
+                        8
+                    ],
+                    "w": 940,
+                    "h": 560
+                },
+                "ext": {
+                    "bidder": {
+                        "placement_id": 1
+                    }
+                }
+            }
+        ],
+        "ext": {
+            "prebid": {
+                "targeting": {
+                    "includebrandcategory": {
+                        "primaryadserver": 1,
+                        "publisher": "anyPublisher",
+                        "withcategory": true
+                    }
+                }
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://ib.adnxs.com/openrtb2",
+                "body": {
+                    "id": "test-request-id",
+                    "ext": {
+                        "appnexus": {
+                            "hb_source": 6,
+                            "brand_category_uniqueness": true,
+                            "include_brand_category": true
+                        },
+                        "prebid": {
+                            "targeting": {
+                                "includebrandcategory": {
+                                    "primaryadserver": 1,
+                                    "publisher": "anyPublisher",
+                                    "withcategory": true
+                                }
+                            }
+                        }
+                    },
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "minduration": 15,
+                                "maxduration": 30,
+                                "protocols": [
+                                    2,
+                                    3,
+                                    5,
+                                    6,
+                                    7,
+                                    8
+                                ],
+                                "w": 940,
+                                "h": 560
+                            },
+                            "ext": {
+                                "appnexus": {
+                                    "placement_id": 1
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "adomain": [
+                                        "appnexus.com"
+                                    ],
+                                    "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "h": 250,
+                                    "w": 300,
+                                    "cat": [
+                                        "IAB9-1"
+                                    ],
+                                    "ext": {
+                                        "appnexus": {
+                                            "brand_id": 9,
+                                            "brand_category_id": 9,
+                                            "auction_id": 8189378542222915032,
+                                            "bid_ad_type": 1,
+                                            "bidder_id": 2,
+                                            "ranking_price": 0.000000,
+                                            "deal_priority": 5
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "appnexus.com"
+                        ],
+                        "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110",
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "cat": [
+                            "IAB5-1"
+                        ],
+                        "ext": {
+                            "appnexus": {
+                                "brand_id": 9,
+                                "brand_category_id": 9,
+                                "auction_id": 8189378542222915032,
+                                "bid_ad_type": 1,
+                                "bidder_id": 2,
+                                "ranking_price": 0.000000,
+                                "deal_priority": 5
+                            }
+                        }
+                    },
+                    "type": "video"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/appnexus/appnexustest/video/video-no-adpodid-two-imps-different-pod.json b/adapters/appnexus/appnexustest/video/video-no-adpodid-two-imps-different-pod.json
index ef1368ab..811cfcb2 100644
--- a/adapters/appnexus/appnexustest/video/video-no-adpodid-two-imps-different-pod.json
+++ b/adapters/appnexus/appnexustest/video/video-no-adpodid-two-imps-different-pod.json
@@ -46,8 +46,7 @@
 			"ext": {
 				"appnexus": {
 				  "hb_source": 6
-				},
-				"prebid": {}
+				}
 			},
 			"imp": [
 			  {
diff --git a/adapters/appnexus/appnexustest/video/video-same-adpodid-two-imps-same-pod.json b/adapters/appnexus/appnexustest/video/video-same-adpodid-two-imps-same-pod.json
index efaf95ed..8f0f1526 100644
--- a/adapters/appnexus/appnexustest/video/video-same-adpodid-two-imps-same-pod.json
+++ b/adapters/appnexus/appnexustest/video/video-same-adpodid-two-imps-same-pod.json
@@ -49,8 +49,7 @@
 				"appnexus": {
 				 "adpod_id": "10",
 				  "hb_source": 6
-				},
-				"prebid": {}
+				}
 			},
 			"imp": [
 			  {
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 8e7ba80b..52813897 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -167,12 +167,9 @@ func TestCharacterEscape(t *testing.T) {
 	var errList []error
 
 	// 	4) Build bid response
-	bidResp, err := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, nil, nil, true, nil, "", errList)
+	bidResp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, nil, nil, true, nil, "", errList)
 
 	// 	5) Assert we have no errors and one '&' character as we are supposed to
-	if err != nil {
-		t.Errorf("exchange.buildBidResponse returned unexpected error: %v", err)
-	}
 	if len(errList) > 0 {
 		t.Errorf("exchange.buildBidResponse returned %d errors", len(errList))
 	}
@@ -1533,10 +1530,7 @@ func TestGetBidCacheInfoEndToEnd(t *testing.T) {
 	var errList []error
 
 	// 	4) Build bid response
-	bid_resp, err := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, auc, nil, true, nil, "", errList)
-
-	// 	5) Assert we have no errors and the bid response we expected
-	assert.NoError(t, err, "[TestGetBidCacheInfo] buildBidResponse() threw an error")
+	bid_resp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, auc, nil, true, nil, "", errList)
 
 	expectedBidResponse := &openrtb2.BidResponse{
 		SeatBid: []openrtb2.SeatBid{
@@ -1909,8 +1903,7 @@ func TestBidResponseCurrency(t *testing.T) {
 	}
 	// Run tests
 	for i := range testCases {
-		actualBidResp, err := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, adapterExtra, nil, bidResponseExt, true, nil, "", errList)
-		assert.NoError(t, err, fmt.Sprintf("[TEST_FAILED] e.buildBidResponse resturns error in test: %s Error message: %s \n", testCases[i].description, err))
+		actualBidResp := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, adapterExtra, nil, bidResponseExt, true, nil, "", errList)
 		assert.Equalf(t, testCases[i].expectedBidResponse, actualBidResp, fmt.Sprintf("[TEST_FAILED] Objects must be equal for test: %s \n Expected: >>%s<< \n Actual: >>%s<< ", testCases[i].description, testCases[i].expectedBidResponse.Ext, actualBidResp.Ext))
 	}
 }
@@ -1976,8 +1969,7 @@ func TestBidResponseImpExtInfo(t *testing.T) {
 
 	expectedBidResponseExt := `{"origbidcpm":0,"prebid":{"type":"video","passthrough":{"imp_passthrough_val":1}},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]}}`
 
-	actualBidResp, err := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, nil, nil, nil, true, impExtInfo, "", errList)
-	assert.NoError(t, err, fmt.Sprintf("imp ext info was not passed through correctly: %s", err))
+	actualBidResp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, nil, nil, nil, true, impExtInfo, "", errList)
 
 	resBidExt := string(actualBidResp.SeatBid[0].Bid[0].Ext)
 	assert.Equalf(t, expectedBidResponseExt, resBidExt, "Expected bid response extension is incorrect")