Skip to content

Commit

Permalink
OTT-1876: Select maximum floor from imp.bidfloor and adunit floor for…
Browse files Browse the repository at this point in the history
… applovinmax endpoint (#829)

* OTT-1876:  Select max of imp.bidfloor and adunitfloor based on feature level setting and applovinmax endpoint
  • Loading branch information
pm-jaydeep-mohite authored Jul 3, 2024
1 parent e39df49 commit 9622a8d
Show file tree
Hide file tree
Showing 16 changed files with 794 additions and 34 deletions.
16 changes: 14 additions & 2 deletions floors/floors.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const (
floorsSkipped = "4"
zeroFloorValue = "5"
highFloorValue = "6"
setMaxFloorValue = "7"
ZERO_FLOOR_VALUE = 0
HIGH_FLOOR_VALUE = 200
)
Expand Down Expand Up @@ -112,8 +113,19 @@ func updateBidRequestWithFloors(extFloorRules *openrtb_ext.PriceFloorRules, requ
if bidFloor > HIGH_FLOOR_VALUE {
metricEngine.RecordFloorStatus(accountID, extFloorRules.PriceFloorLocation, highFloorValue)
}
imp.BidFloor = bidFloor
imp.BidFloorCur = floorCur

if extFloorRules.SetMaxFloor {
floorVal, floorCur, floorLoc := GetMaxFloorValue(imp.BidFloor, imp.BidFloorCur, floorVal, floorCur, conversions)
imp.BidFloor = floorVal
imp.BidFloorCur = floorCur
if floorLoc != "" {
extFloorRules.PriceFloorLocation = openrtb_ext.RequestLocation
metricEngine.RecordFloorStatus(accountID, extFloorRules.PriceFloorLocation, setMaxFloorValue)
}
} else {
imp.BidFloor = bidFloor
imp.BidFloorCur = floorCur
}

err = updateImpExtWithFloorDetails(imp, matchedRule, floorVal, imp.BidFloor)
if err != nil {
Expand Down
94 changes: 93 additions & 1 deletion floors/floors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,6 @@ func TestUpdateBidRequestWithFloors(t *testing.T) {
args args
setup func()
}{

{
name: "test record floor status with no failures",
args: args{
Expand Down Expand Up @@ -2191,11 +2190,104 @@ func TestUpdateBidRequestWithFloors(t *testing.T) {
me.On("RecordFloorStatus", "5890", "request", "6").Return()
},
},
{
name: "setmax floor disabled, and imp.bidfloor > floor value",
args: args{
extFloorRules: &openrtb_ext.PriceFloorRules{
Enabled: getTrue(),
FloorMinCur: "USD",
PriceFloorLocation: openrtb_ext.RequestLocation,
Enforcement: &openrtb_ext.PriceFloorEnforcement{
EnforcePBS: getTrue(),
EnforceRate: 100,
FloorDeals: getTrue(),
},

Data: &openrtb_ext.PriceFloorData{
Currency: "USD",
ModelGroups: []openrtb_ext.PriceFloorModelGroup{
{
ModelVersion: "model 1 from req",
Currency: "USD",
Values: map[string]float64{
"banner|300x600|www.website5.com": 5,
"*|*|*": 21,
},
Schema: openrtb_ext.PriceFloorSchema{
Fields: []string{"mediaType", "size", "domain"},
Delimiter: "|",
},
},
},
}},
request: &openrtb_ext.RequestWrapper{
BidRequest: &openrtb2.BidRequest{
Site: &openrtb2.Site{
Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
},
Imp: []openrtb2.Imp{{ID: "1234", BidFloor: 50, BidFloorCur: "USD", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
},
},
accountID: "5890",
},

setup: func() {
},
},
{
name: "setmax floor enabled, and imp.bidfloor > floor value",
args: args{
extFloorRules: &openrtb_ext.PriceFloorRules{
Enabled: getTrue(),
FloorMinCur: "USD",
SetMaxFloor: true,
PriceFloorLocation: openrtb_ext.RequestLocation,
Enforcement: &openrtb_ext.PriceFloorEnforcement{
EnforcePBS: getTrue(),
EnforceRate: 100,
FloorDeals: getTrue(),
},

Data: &openrtb_ext.PriceFloorData{
Currency: "USD",
ModelGroups: []openrtb_ext.PriceFloorModelGroup{
{
ModelVersion: "model 1 from req",
Currency: "USD",
Values: map[string]float64{
"banner|300x600|www.website5.com": 5,
"*|*|*": 21,
},
Schema: openrtb_ext.PriceFloorSchema{
Fields: []string{"mediaType", "size", "domain"},
Delimiter: "|",
},
},
},
}},
request: &openrtb_ext.RequestWrapper{
BidRequest: &openrtb2.BidRequest{
Site: &openrtb2.Site{
Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
},
Imp: []openrtb2.Imp{{ID: "1234", BidFloor: 50, BidFloorCur: "USD", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
},
},
accountID: "5890",
},

setup: func() {
me.On("RecordFloorStatus", "5890", "request", "7").Return()
},
},
}
for _, test := range tests {
if test.setup != nil {
test.setup()
}
updateBidRequestWithFloors(test.args.extFloorRules, test.args.request, test.args.conversions, me, test.args.accountID)
assert.True(t, me.AssertExpectations(t))
}
}
26 changes: 26 additions & 0 deletions floors/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,32 @@ func getFloorCurrency(floorExt *openrtb_ext.PriceFloorRules) string {
return floorCur
}

// GetMaxFloorValue returns maximum floor value from imp.bidfloor and floor rule value
func GetMaxFloorValue(impFloor float64, impFloorCur string, floorRuleValue float64, floorRuleCur string, conversions currency.Conversions) (float64, string, string) {
if impFloorCur == "" {
impFloorCur = defaultCurrency
}

if floorRuleCur == "" {
floorRuleCur = defaultCurrency
}

if impFloorCur != floorRuleCur {
rate, err := conversions.GetRate(impFloorCur, floorRuleCur)
if err != nil {
return floorRuleValue, floorRuleCur, ""
}

if floorVal := rate * impFloor; floorVal > floorRuleValue {
return impFloor, impFloorCur, openrtb_ext.RequestLocation
}
} else if impFloor > floorRuleValue {
return impFloor, impFloorCur, openrtb_ext.RequestLocation
}

return floorRuleValue, floorRuleCur, ""
}

// getMinFloorValue returns floorMin and floorMinCur,
// values provided in impression extension are considered over floors JSON.
func getMinFloorValue(floorExt *openrtb_ext.PriceFloorRules, imp *openrtb_ext.ImpWrapper, conversions currency.Conversions) (float64, string, error) {
Expand Down
126 changes: 126 additions & 0 deletions floors/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1221,3 +1221,129 @@ func getIntPtr(v int) *int {
func getInt64Ptr(v int64) *int64 {
return &v
}

func TestGetMaxFloorValue(t *testing.T) {
rates := map[string]map[string]float64{
"USD": {
"INR": 81.17,
},
}
type args struct {
impFloor float64
impFloorCur string
floorRuleValue float64
floorRuleCur string
}
tests := []struct {
name string
args args
expFloorValue float64
expFloorCur string
expFloorLocation string
}{
{
name: "Same Currency, ImpFloor value is less than floor rule value",
args: args{
impFloor: 1.0,
impFloorCur: "USD",
floorRuleValue: 2.0,
floorRuleCur: "USD",
},
expFloorValue: 2.0,
expFloorCur: "USD",
expFloorLocation: "",
},
{
name: "Same Currency, ImpFloor value is higher than floor rule value",
args: args{
impFloor: 3.0,
impFloorCur: "USD",
floorRuleValue: 2.0,
floorRuleCur: "USD",
},
expFloorValue: 3.0,
expFloorCur: "USD",
expFloorLocation: openrtb_ext.RequestLocation,
},
{
name: "Different Currency, ImpFloor value is higher than floor rule value",
args: args{
impFloor: 10.0,
impFloorCur: "USD",
floorRuleValue: 100.0,
floorRuleCur: "INR",
},
expFloorValue: 10.0,
expFloorCur: "USD",
expFloorLocation: openrtb_ext.RequestLocation,
},
{
name: "Different Currency, ImpFloor value is less than floor rule value",
args: args{
impFloor: 120.0,
impFloorCur: "INR",
floorRuleValue: 2.0,
floorRuleCur: "USD",
},
expFloorValue: 2.0,
expFloorCur: "USD",
expFloorLocation: "",
},
{
name: "Different Currency, ImpFloor value higher than floor rule value",
args: args{
impFloor: 190.0,
impFloorCur: "INR",
floorRuleValue: 2.0,
floorRuleCur: "USD",
},
expFloorValue: 190.0,
expFloorCur: "INR",
expFloorLocation: openrtb_ext.RequestLocation,
},
{
name: "ImpFloorCur empty & impFloor value is greater than floor rule value",
args: args{
impFloor: 15.0,
impFloorCur: "",
floorRuleValue: 10.0,
floorRuleCur: "USD",
},
expFloorValue: 15.0,
expFloorCur: "USD",
expFloorLocation: openrtb_ext.RequestLocation,
},
{
name: "ImpFloor value is less than floor rule value, floorRuleCur empty",
args: args{
impFloor: 7,
impFloorCur: "USD",
floorRuleValue: 15,
floorRuleCur: "",
},
expFloorValue: 15.0,
expFloorCur: "USD",
expFloorLocation: "",
},
{
name: "ImpFloor value is less than floor rule value, floorRuleCur, ImpFlorCut empty",
args: args{
impFloor: 5,
impFloorCur: "",
floorRuleValue: 7,
floorRuleCur: "",
},
expFloorValue: 7.0,
expFloorCur: "USD",
expFloorLocation: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actualFloorValue, actualFloorCur, actualFloorLocation := GetMaxFloorValue(tt.args.impFloor, tt.args.impFloorCur, tt.args.floorRuleValue, tt.args.floorRuleCur, getCurrencyRates(rates))
assert.Equal(t, tt.expFloorValue, actualFloorValue)
assert.Equal(t, tt.expFloorCur, actualFloorCur)
assert.Equal(t, tt.expFloorLocation, actualFloorLocation)
})
}
}
44 changes: 26 additions & 18 deletions modules/pubmatic/openwrap/beforevalidationhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/openrtb/v20/openrtb3"
"github.com/prebid/prebid-server/v2/currency"
"github.com/prebid/prebid-server/v2/floors"
"github.com/prebid/prebid-server/v2/hooks/hookstage"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/adapters"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/adpod"
Expand Down Expand Up @@ -90,6 +91,7 @@ func (m OpenWrap) handleBeforeValidationHook(
rCtx.IP = getIP(payload.BidRequest, rCtx.IP)
rCtx.Country = getCountry(payload.BidRequest)
rCtx.DeviceCtx.Platform = getDevicePlatform(rCtx, payload.BidRequest)
rCtx.IsMaxFloorsEnabled = rCtx.Endpoint == models.EndpointAppLovinMax && m.pubFeatures.IsMaxFloorsEnabled(rCtx.PubID)
populateDeviceContext(&rCtx.DeviceCtx, payload.BidRequest.Device)

if rCtx.IsCTVRequest {
Expand Down Expand Up @@ -590,7 +592,7 @@ func (m OpenWrap) handleBeforeValidationHook(
}

adunitconfig.UpdateFloorsExtObjectFromAdUnitConfig(rCtx, requestExt)
setFloorsExt(requestExt, rCtx.PartnerConfigMap)
setFloorsExt(requestExt, rCtx.PartnerConfigMap, rCtx.IsMaxFloorsEnabled)

if len(rCtx.Aliases) != 0 && requestExt.Prebid.Aliases == nil {
requestExt.Prebid.Aliases = make(map[string]string)
Expand Down Expand Up @@ -734,15 +736,10 @@ func (m *OpenWrap) applyVideoAdUnitConfig(rCtx models.RequestCtx, imp *openrtb2.
}

impBidCtx := rCtx.ImpBidCtx[imp.ID]
if imp.BidFloor == 0 && adUnitCfg.BidFloor != nil {
imp.BidFloor = *adUnitCfg.BidFloor
impBidCtx.BidFloor = imp.BidFloor
}
imp.BidFloor, imp.BidFloorCur = setImpBidFloorParams(rCtx, adUnitCfg, imp, m.rateConvertor.Rates())
impBidCtx.BidFloor = imp.BidFloor
impBidCtx.BidFloorCur = imp.BidFloorCur

if len(imp.BidFloorCur) == 0 && adUnitCfg.BidFloorCur != nil {
imp.BidFloorCur = *adUnitCfg.BidFloorCur
impBidCtx.BidFloorCur = imp.BidFloorCur
}
rCtx.ImpBidCtx[imp.ID] = impBidCtx

if adUnitCfg.Exp != nil {
Expand Down Expand Up @@ -774,6 +771,23 @@ func (m *OpenWrap) applyVideoAdUnitConfig(rCtx models.RequestCtx, imp *openrtb2.
updateImpVideoWithVideoConfig(imp, adUnitCfg.Video.Config)
}
}
func setImpBidFloorParams(rCtx models.RequestCtx, adUnitCfg *modelsAdunitConfig.AdConfig, imp *openrtb2.Imp, conversions currency.Conversions) (float64, string) {
bidfloor := imp.BidFloor
bidfloorcur := imp.BidFloorCur

if rCtx.IsMaxFloorsEnabled && adUnitCfg.BidFloor != nil {
bidfloor, bidfloorcur, _ = floors.GetMaxFloorValue(imp.BidFloor, imp.BidFloorCur, *adUnitCfg.BidFloor, *adUnitCfg.BidFloorCur, conversions)
} else {
if imp.BidFloor == 0 && adUnitCfg.BidFloor != nil {
bidfloor = *adUnitCfg.BidFloor
}

if len(imp.BidFloorCur) == 0 && adUnitCfg.BidFloorCur != nil {
bidfloorcur = *adUnitCfg.BidFloorCur
}
}
return bidfloor, bidfloorcur
}

func (m *OpenWrap) applyBannerAdUnitConfig(rCtx models.RequestCtx, imp *openrtb2.Imp) {
if imp.Banner == nil {
Expand All @@ -786,15 +800,9 @@ func (m *OpenWrap) applyBannerAdUnitConfig(rCtx models.RequestCtx, imp *openrtb2
}

impBidCtx := rCtx.ImpBidCtx[imp.ID]
if imp.BidFloor == 0 && adUnitCfg.BidFloor != nil {
imp.BidFloor = *adUnitCfg.BidFloor
impBidCtx.BidFloor = imp.BidFloor
}

if len(imp.BidFloorCur) == 0 && adUnitCfg.BidFloorCur != nil {
imp.BidFloorCur = *adUnitCfg.BidFloorCur
impBidCtx.BidFloorCur = imp.BidFloorCur
}
imp.BidFloor, imp.BidFloorCur = setImpBidFloorParams(rCtx, adUnitCfg, imp, m.rateConvertor.Rates())
impBidCtx.BidFloor = imp.BidFloor
impBidCtx.BidFloorCur = imp.BidFloorCur
rCtx.ImpBidCtx[imp.ID] = impBidCtx

if adUnitCfg.Exp != nil {
Expand Down
Loading

0 comments on commit 9622a8d

Please sign in to comment.