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

Commit

Permalink
Add cpmOverride (prebid#1289)
Browse files Browse the repository at this point in the history
* Add cpmOverride

Enabled `request.ext.rubicon.debug.cpmOverride` and `request.imp[].ext.rubicon.debug.cpmOverride` processing.
Updates tests

* Remove unnecessary error checks and add shallow copy

* Fixed same pointer
  • Loading branch information
DGarbar authored May 14, 2020
1 parent 5dec103 commit 7bc6b92
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 11 deletions.
71 changes: 62 additions & 9 deletions adapters/rubicon/rubicon.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ type rubiconParams struct {
Video rubiconVideoParams `json:"video"`
}

type bidRequestExt struct {
Rubicon bidRequestExtRubicon `json:"rubicon,omitempty"`
}

type bidRequestExtRubicon struct {
Debug bidRequestExtRubiconDebug `json:"debug,omitempty"`
}

type bidRequestExtRubiconDebug struct {
CpmOverride float64 `json:"cpmOverride,omitempty"`
}

type rubiconImpExtRPTrack struct {
Mint string `json:"mint"`
MintVersion string `json:"mint_version"`
Expand Down Expand Up @@ -578,6 +590,7 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adap

requestImpCopy := request.Imp

rubiconRequest := *request
for i := 0; i < numRequests; i++ {
thisImp := requestImpCopy[i]

Expand Down Expand Up @@ -677,14 +690,14 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adap
errs = append(errs, err)
continue
}
request.User = &userCopy
rubiconRequest.User = &userCopy
}

if request.Device != nil {
deviceCopy := *request.Device
deviceExt := rubiconDeviceExt{RP: rubiconDeviceExtRP{PixelRatio: request.Device.PxRatio}}
deviceCopy.Ext, err = json.Marshal(&deviceExt)
request.Device = &deviceCopy
rubiconRequest.Device = &deviceCopy
}

isVideo := isVideo(thisImp)
Expand Down Expand Up @@ -732,28 +745,28 @@ func (a *RubiconAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adap
siteCopy.Ext, err = json.Marshal(&siteExt)
siteCopy.Publisher = &openrtb.Publisher{}
siteCopy.Publisher.Ext, err = json.Marshal(&pubExt)
request.Site = &siteCopy
rubiconRequest.Site = &siteCopy
}
if request.App != nil {
appCopy := *request.App
appCopy.Ext, err = json.Marshal(&siteExt)
appCopy.Publisher = &openrtb.Publisher{}
appCopy.Publisher.Ext, err = json.Marshal(&pubExt)
request.App = &appCopy
rubiconRequest.App = &appCopy
}

reqBadv := request.BAdv
if reqBadv != nil {
if len(reqBadv) > badvLimitSize {
request.BAdv = reqBadv[:badvLimitSize]
rubiconRequest.BAdv = reqBadv[:badvLimitSize]
}
}

request.Imp = []openrtb.Imp{thisImp}
request.Cur = nil
request.Ext = nil
rubiconRequest.Imp = []openrtb.Imp{thisImp}
rubiconRequest.Cur = nil
rubiconRequest.Ext = nil

reqJSON, err := json.Marshal(request)
reqJSON, err := json.Marshal(rubiconRequest)
if err != nil {
errs = append(errs, err)
continue
Expand Down Expand Up @@ -900,9 +913,22 @@ func (a *RubiconAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalR
bidType = openrtb_ext.BidTypeVideo
}

impToCpmOverride := mapImpIdToCpmOverride(internalRequest.Imp)
cmpOverride := cmpOverrideFromBidRequest(internalRequest)

for _, sb := range bidResp.SeatBid {
for i := 0; i < len(sb.Bid); i++ {
bid := sb.Bid[i]

bidCmpOverride, ok := impToCpmOverride[bid.ImpID]
if !ok || bidCmpOverride == 0 {
bidCmpOverride = cmpOverride
}

if bidCmpOverride > 0 {
bid.Price = bidCmpOverride
}

if bid.Price != 0 {
// Since Rubicon XAPI returns only one bid per response
// copy response.bidid to openrtb_response.seatbid.bid.bidid
Expand All @@ -919,3 +945,30 @@ func (a *RubiconAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalR

return bidResponse, nil
}

func cmpOverrideFromBidRequest(bidRequest *openrtb.BidRequest) float64 {
var bidRequestExt bidRequestExt
if err := json.Unmarshal(bidRequest.Ext, &bidRequestExt); err != nil {
return 0
}

return bidRequestExt.Rubicon.Debug.CpmOverride
}

func mapImpIdToCpmOverride(imps []openrtb.Imp) map[string]float64 {
impIdToCmpOverride := make(map[string]float64)
for _, imp := range imps {
var bidderExt adapters.ExtImpBidder
if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
continue
}

var rubiconExt openrtb_ext.ExtImpRubicon
if err := json.Unmarshal(bidderExt.Bidder, &rubiconExt); err != nil {
continue
}

impIdToCmpOverride[imp.ID] = rubiconExt.Debug.CpmOverride
}
return impIdToCmpOverride
}
97 changes: 95 additions & 2 deletions adapters/rubicon/rubicon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -973,9 +973,9 @@ func TestOpenRTBRequest(t *testing.T) {
}

assert.Equal(t, request.ID, rpRequest.ID, "Bad Request ID. Expected %s, Got %s", request.ID, rpRequest.ID)
assert.Equal(t, len(request.Imp), len(rpRequest.Imp), "Wrong len(request.Imp). Expected %d, Got %d", len(request.Imp), len(rpRequest.Imp))
assert.Equal(t, 1, len(rpRequest.Imp), "Wrong len(request.Imp). Expected %d, Got %d", len(request.Imp), len(rpRequest.Imp))
assert.Nil(t, rpRequest.Cur, "Wrong request.Cur. Expected nil, Got %s", rpRequest.Cur)
assert.Nil(t, request.Ext, "Wrong request.ext. Expected nil, Got %v", request.Ext)
assert.Nil(t, rpRequest.Ext, "Wrong request.ext. Expected nil, Got %v", rpRequest.Ext)

if rpRequest.Imp[0].ID == "test-imp-banner-id" {
var rpExt rubiconBannerExt
Expand Down Expand Up @@ -1425,6 +1425,99 @@ func TestOpenRTBStandardResponse(t *testing.T) {
assert.Equal(t, "1234567890", theBid.ID, "Bad bid ID. Expected %s, got %s", "1234567890", theBid.ID)
}

func TestOpenRTBResponseOverridePriceFromBidRequest(t *testing.T) {
request := &openrtb.BidRequest{
ID: "test-request-id",
Imp: []openrtb.Imp{{
ID: "test-imp-id",
Banner: &openrtb.Banner{
Format: []openrtb.Format{{
W: 320,
H: 50,
}},
},
Ext: json.RawMessage(`{"bidder": {
"accountId": 2763,
"siteId": 68780,
"zoneId": 327642
}}`),
}},
Ext: json.RawMessage(`{"rubicon": {
"debug": {
"cpmOverride" : 10
}}}`),
}

requestJson, _ := json.Marshal(request)
reqData := &adapters.RequestData{
Method: "POST",
Uri: "test-uri",
Body: requestJson,
Headers: nil,
}

httpResp := &adapters.ResponseData{
StatusCode: http.StatusOK,
Body: []byte(`{"id":"test-request-id","seatbid":[{"bid":[{"id":"1234567890","impid":"test-imp-id","price": 2,"crid":"4122982","adm":"some ad","h": 50,"w": 320,"ext":{"bidder":{"rp":{"targeting": {"key": "rpfl_2763", "values":["43_tier0100"]},"mime": "text/html","size_id": 43}}}}]}]}`),
}

bidder := new(RubiconAdapter)
bidResponse, errs := bidder.MakeBids(request, reqData, httpResp)

assert.Empty(t, errs, "Expected 0 errors. Got %d", len(errs))

assert.Equal(t, float64(10), bidResponse.Bids[0].Bid.Price,
"Expected Price 10. Got: %s", bidResponse.Bids[0].Bid.Price)
}

func TestOpenRTBResponseOverridePriceFromCorrespondingImp(t *testing.T) {
request := &openrtb.BidRequest{
ID: "test-request-id",
Imp: []openrtb.Imp{{
ID: "test-imp-id",
Banner: &openrtb.Banner{
Format: []openrtb.Format{{
W: 320,
H: 50,
}},
},
Ext: json.RawMessage(`{"bidder": {
"accountId": 2763,
"siteId": 68780,
"zoneId": 327642,
"debug": {
"cpmOverride" : 20
}
}}`),
}},
Ext: json.RawMessage(`{"rubicon": {
"debug": {
"cpmOverride" : 10
}}}`),
}

requestJson, _ := json.Marshal(request)
reqData := &adapters.RequestData{
Method: "POST",
Uri: "test-uri",
Body: requestJson,
Headers: nil,
}

httpResp := &adapters.ResponseData{
StatusCode: http.StatusOK,
Body: []byte(`{"id":"test-request-id","seatbid":[{"bid":[{"id":"1234567890","impid":"test-imp-id","price": 2,"crid":"4122982","adm":"some ad","h": 50,"w": 320,"ext":{"bidder":{"rp":{"targeting": {"key": "rpfl_2763", "values":["43_tier0100"]},"mime": "text/html","size_id": 43}}}}]}]}`),
}

bidder := new(RubiconAdapter)
bidResponse, errs := bidder.MakeBids(request, reqData, httpResp)

assert.Empty(t, errs, "Expected 0 errors. Got %d", len(errs))

assert.Equal(t, float64(20), bidResponse.Bids[0].Bid.Price,
"Expected Price 20. Got: %s", bidResponse.Bids[0].Bid.Price)
}

func TestOpenRTBCopyBidIdFromResponseIfZero(t *testing.T) {
request := &openrtb.BidRequest{
ID: "test-request-id",
Expand Down
6 changes: 6 additions & 0 deletions openrtb_ext/imp_rubicon.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type ExtImpRubicon struct {
Inventory json.RawMessage `json:"inventory,omitempty"`
Visitor json.RawMessage `json:"visitor,omitempty"`
Video rubiconVideoParams `json:"video"`
Debug impExtRubiconDebug `json:"debug,omitempty"`
}

// rubiconVideoParams defines the contract for bidrequest.imp[i].ext.rubicon.video
Expand All @@ -23,3 +24,8 @@ type rubiconVideoParams struct {
Skip int `json:"skip,omitempty"`
SkipDelay int `json:"skipdelay,omitempty"`
}

// rubiconVideoParams defines the contract for bidrequest.imp[i].ext.rubicon.debug
type impExtRubiconDebug struct {
CpmOverride float64 `json:"cpmOverride,omitempty"`
}

0 comments on commit 7bc6b92

Please sign in to comment.