Skip to content
This repository has been archived by the owner on Dec 22, 2022. It is now read-only.

Commit

Permalink
Adding translatecategories flag to includebrandcategory (prebid#1098)
Browse files Browse the repository at this point in the history
* Making IAB category translation optional with translatecategories boolean in request

* Updating exchange unit tests to remove extra bids

* Updates from code review comments

* Removed comment about default TranslateCategories value
* Changed translateCat to translateCategories in tests
* Combined helper functions in exchange_test related to TranslateCategories
  • Loading branch information
camrice authored and hhhjort committed Nov 11, 2019
1 parent 7850b77 commit 28aa6b2
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 24 deletions.
7 changes: 4 additions & 3 deletions endpoints/openrtb2/video_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,10 @@ func createBidExtension(videoRequest *openrtb_ext.BidRequestVideo) ([]byte, erro
var inclBrandCat *openrtb_ext.ExtIncludeBrandCategory
if videoRequest.IncludeBrandCategory != nil {
inclBrandCat = &openrtb_ext.ExtIncludeBrandCategory{
PrimaryAdServer: videoRequest.IncludeBrandCategory.PrimaryAdserver,
Publisher: videoRequest.IncludeBrandCategory.Publisher,
WithCategory: true,
PrimaryAdServer: videoRequest.IncludeBrandCategory.PrimaryAdserver,
Publisher: videoRequest.IncludeBrandCategory.Publisher,
WithCategory: true,
TranslateCategories: videoRequest.IncludeBrandCategory.TranslateCategories,
}
} else {
inclBrandCat = &openrtb_ext.ExtIncludeBrandCategory{
Expand Down
12 changes: 8 additions & 4 deletions endpoints/openrtb2/video_auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,12 @@ func TestCreateBidExtension(t *testing.T) {
Increment: 0.1,
})

translateCategories := true
videoRequest := openrtb_ext.BidRequestVideo{
IncludeBrandCategory: &openrtb_ext.IncludeBrandCategory{
PrimaryAdserver: 1,
Publisher: "",
PrimaryAdserver: 1,
Publisher: "",
TranslateCategories: &translateCategories,
},
PodConfig: openrtb_ext.PodConfig{
DurationRangeSec: durationRange,
Expand Down Expand Up @@ -138,10 +140,12 @@ func TestCreateBidExtensionExactDurTrueNoPriceRange(t *testing.T) {
durationRange = append(durationRange, 15)
durationRange = append(durationRange, 30)

translateCategories := false
videoRequest := openrtb_ext.BidRequestVideo{
IncludeBrandCategory: &openrtb_ext.IncludeBrandCategory{
PrimaryAdserver: 1,
Publisher: "",
PrimaryAdserver: 1,
Publisher: "",
TranslateCategories: &translateCategories,
},
PodConfig: openrtb_ext.PodConfig{
DurationRangeSec: durationRange,
Expand Down
37 changes: 24 additions & 13 deletions exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,21 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest
var primaryAdServer string
var publisher string
var err error
var translateCategories = true

if includeBrandCategory && brandCatExt.WithCategory {
//if ext.prebid.targeting.includebrandcategory present but primaryadserver/publisher not present then error out the request right away.
primaryAdServer, err = getPrimaryAdServer(brandCatExt.PrimaryAdServer) //1-Freewheel 2-DFP
if err != nil {
return res, seatBids, err
if brandCatExt.TranslateCategories != nil {
translateCategories = *brandCatExt.TranslateCategories
}
//if translateCategories is set to false, ignore checking primaryAdServer and publisher
if translateCategories {
//if ext.prebid.targeting.includebrandcategory present but primaryadserver/publisher not present then error out the request right away.
primaryAdServer, err = getPrimaryAdServer(brandCatExt.PrimaryAdServer) //1-Freewheel 2-DFP
if err != nil {
return res, seatBids, err
}
publisher = brandCatExt.Publisher
}
publisher = brandCatExt.Publisher
}

seatBidsToRemove := make([]openrtb_ext.BidderName, 0)
Expand All @@ -387,15 +394,19 @@ func applyCategoryMapping(ctx context.Context, requestExt openrtb_ext.ExtRequest
bidsToRemove = append(bidsToRemove, bidInd)
continue
}
//if unique IAB category is present then translate it to the adserver category based on mapping file
category, err = categoriesFetcher.FetchCategories(ctx, primaryAdServer, publisher, bidIabCat[0])
if err != nil || category == "" {
//TODO: add metrics
//if mapping required but no mapping file is found then discard the bid
bidsToRemove = append(bidsToRemove, bidInd)
continue
if translateCategories {
//if unique IAB category is present then translate it to the adserver category based on mapping file
category, err = categoriesFetcher.FetchCategories(ctx, primaryAdServer, publisher, bidIabCat[0])
if err != nil || category == "" {
//TODO: add metrics
//if mapping required but no mapping file is found then discard the bid
bidsToRemove = append(bidsToRemove, bidInd)
continue
}
} else {
//category translation is disabled, continue with IAB category
category = bidIabCat[0]
}

}

// TODO: consider should we remove bids with zero duration here?
Expand Down
133 changes: 132 additions & 1 deletion exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,8 @@ func newExtRequest() openrtb_ext.ExtRequest {
},
}

brandCat := openrtb_ext.ExtIncludeBrandCategory{PrimaryAdServer: 1, WithCategory: true}
translateCategories := true
brandCat := openrtb_ext.ExtIncludeBrandCategory{PrimaryAdServer: 1, WithCategory: true, TranslateCategories: &translateCategories}

reqExt := openrtb_ext.ExtRequestTargeting{
PriceGranularity: priceGran,
Expand Down Expand Up @@ -676,6 +677,136 @@ func TestCategoryMappingNoIncludeBrandCategory(t *testing.T) {
assert.Equal(t, 4, len(bidCategory), "Bidders category mapping doesn't match")
}

func TestCategoryMappingTranslateCategoriesNil(t *testing.T) {

categoriesFetcher, error := newCategoryFetcher("./test/category-mapping")
if error != nil {
t.Errorf("Failed to create a category Fetcher: %v", error)
}

requestExt := newExtRequestTranslateCategories(nil)

targData := &targetData{
priceGranularity: requestExt.Prebid.Targeting.PriceGranularity,
includeWinners: true,
}

requestExt.Prebid.Targeting.DurationRangeSec = []int{15, 30, 50}

adapterBids := make(map[openrtb_ext.BidderName]*pbsOrtbSeatBid)

cats1 := []string{"IAB1-3"}
cats2 := []string{"IAB1-4"}
cats3 := []string{"IAB1-1000"}
bid1 := openrtb.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 20.0000, Cat: cats2, W: 1, H: 1}
bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}

bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}}
bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}}
bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}}

innerBids := []*pbsOrtbBid{
&bid1_1,
&bid1_2,
&bid1_3,
}

seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
bidderName1 := openrtb_ext.BidderName("appnexus")

adapterBids[bidderName1] = &seatBid

bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData)

assert.Equal(t, nil, err, "Category mapping error should be empty")
assert.Equal(t, "10.00_Electronics_30s", bidCategory["bid_id1"], "Category mapping doesn't match")
assert.Equal(t, "20.00_Sports_50s", bidCategory["bid_id2"], "Category mapping doesn't match")
assert.Equal(t, 2, len(adapterBids[bidderName1].bids), "Bidders number doesn't match")
assert.Equal(t, 2, len(bidCategory), "Bidders category mapping doesn't match")
}

func newExtRequestTranslateCategories(translateCategories *bool) openrtb_ext.ExtRequest {
priceGran := openrtb_ext.PriceGranularity{
Precision: 2,
Ranges: []openrtb_ext.GranularityRange{
{
Min: 0.0,
Max: 20.0,
Increment: 2.0,
},
},
}

brandCat := openrtb_ext.ExtIncludeBrandCategory{WithCategory: true, PrimaryAdServer: 1}
if translateCategories != nil {
brandCat.TranslateCategories = translateCategories
}

reqExt := openrtb_ext.ExtRequestTargeting{
PriceGranularity: priceGran,
IncludeWinners: true,
IncludeBrandCategory: &brandCat,
}

return openrtb_ext.ExtRequest{
Prebid: openrtb_ext.ExtRequestPrebid{
Targeting: &reqExt,
},
}
}

func TestCategoryMappingTranslateCategoriesFalse(t *testing.T) {

categoriesFetcher, error := newCategoryFetcher("./test/category-mapping")
if error != nil {
t.Errorf("Failed to create a category Fetcher: %v", error)
}

translateCategories := false
requestExt := newExtRequestTranslateCategories(&translateCategories)

targData := &targetData{
priceGranularity: requestExt.Prebid.Targeting.PriceGranularity,
includeWinners: true,
}

requestExt.Prebid.Targeting.DurationRangeSec = []int{15, 30, 50}

adapterBids := make(map[openrtb_ext.BidderName]*pbsOrtbSeatBid)

cats1 := []string{"IAB1-3"}
cats2 := []string{"IAB1-4"}
cats3 := []string{"IAB1-1000"}
bid1 := openrtb.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, Cat: cats1, W: 1, H: 1}
bid2 := openrtb.Bid{ID: "bid_id2", ImpID: "imp_id2", Price: 20.0000, Cat: cats2, W: 1, H: 1}
bid3 := openrtb.Bid{ID: "bid_id3", ImpID: "imp_id3", Price: 30.0000, Cat: cats3, W: 1, H: 1}

bid1_1 := pbsOrtbBid{&bid1, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}}
bid1_2 := pbsOrtbBid{&bid2, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 40}}
bid1_3 := pbsOrtbBid{&bid3, "video", nil, &openrtb_ext.ExtBidPrebidVideo{Duration: 30}}

innerBids := []*pbsOrtbBid{
&bid1_1,
&bid1_2,
&bid1_3,
}

seatBid := pbsOrtbSeatBid{innerBids, "USD", nil, nil}
bidderName1 := openrtb_ext.BidderName("appnexus")

adapterBids[bidderName1] = &seatBid

bidCategory, adapterBids, err := applyCategoryMapping(nil, requestExt, adapterBids, categoriesFetcher, targData)

assert.Equal(t, nil, err, "Category mapping error should be empty")
assert.Equal(t, "10.00_IAB1-3_30s", bidCategory["bid_id1"], "Category should not be translated")
assert.Equal(t, "20.00_IAB1-4_50s", bidCategory["bid_id2"], "Category should not be translated")
assert.Equal(t, "20.00_IAB1-1000_30s", bidCategory["bid_id3"], "Bid should not be rejected")
assert.Equal(t, 3, len(adapterBids[bidderName1].bids), "Bidders number doesn't match")
assert.Equal(t, 3, len(bidCategory), "Bidders category mapping doesn't match")
}

func TestCategoryDedupe(t *testing.T) {

categoriesFetcher, error := newCategoryFetcher("./test/category-mapping")
Expand Down
8 changes: 8 additions & 0 deletions openrtb_ext/bid_request_video.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ type IncludeBrandCategory struct {
// string; optional
// Identifier for the Publisher
Publisher string `json:"publisher"`

// Attribute:
// translatecategories
// Type:
// *bool; optional
// Description:
// Indicates if IAB categories should be translated to adserver category
TranslateCategories *bool `json:"translatecategories,omitempty"`
}

type Cacheconfig struct {
Expand Down
7 changes: 4 additions & 3 deletions openrtb_ext/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ type ExtRequestTargeting struct {
}

type ExtIncludeBrandCategory struct {
PrimaryAdServer int `json:"primaryadserver"`
Publisher string `json:"publisher"`
WithCategory bool `json:"withcategory"`
PrimaryAdServer int `json:"primaryadserver"`
Publisher string `json:"publisher"`
WithCategory bool `json:"withcategory"`
TranslateCategories *bool `json:"translatecategories,omitempty"`
}

// Make an unmarshaller that will set a default PriceGranularity
Expand Down

0 comments on commit 28aa6b2

Please sign in to comment.