Skip to content

Commit 6e99a15

Browse files
Merge branch 'ci' into UOE-12292
2 parents 742c02f + 3171867 commit 6e99a15

File tree

12 files changed

+497
-177
lines changed

12 files changed

+497
-177
lines changed

endpoints/openrtb2/auction.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ func sendAuctionResponse(
390390

391391
if response != nil {
392392
ao.HookExecutionOutcome = stageOutcomes
393+
removeDefaultBidsFromSeatNonBid(seatNonBid, &ao)
393394
UpdateResponseExtOW(w, response, ao)
394395
err := setSeatNonBidRaw(ao.RequestWrapper, response, ao.SeatNonBid)
395396
if err != nil {

endpoints/openrtb2/auction_ow.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,29 @@ func UpdateResponseExtOW(w http.ResponseWriter, bidResponse *openrtb2.BidRespons
8686
rCtx.WakandaDebug.SetHTTPResponseWriter(w)
8787
}
8888
}
89+
90+
func removeDefaultBidsFromSeatNonBid(seatNonBid *openrtb_ext.SeatNonBidBuilder, ao *analytics.AuctionObject) {
91+
if seatNonBid == nil {
92+
return
93+
}
94+
95+
for seat, nonBids := range *seatNonBid {
96+
// First pass: count number of bids per ImpID
97+
impCount := make(map[string]int)
98+
for _, bid := range nonBids {
99+
impCount[bid.ImpId]++
100+
}
101+
102+
// Second pass: remove default bids with StatusCode == 0 only if that ImpID has >1 bid
103+
cleanedNonSeatBids := make([]openrtb_ext.NonBid, 0, len(nonBids))
104+
for _, bid := range nonBids {
105+
if impCount[bid.ImpId] > 1 && bid.StatusCode == 0 {
106+
glog.V(3).Infof("Removing Default bid from seatNonBid of seat %s and impid %s", seat, bid.ImpId)
107+
continue
108+
}
109+
cleanedNonSeatBids = append(cleanedNonSeatBids, bid)
110+
}
111+
(*seatNonBid)[seat] = cleanedNonSeatBids
112+
}
113+
ao.SeatNonBid = seatNonBid.Get()
114+
}

endpoints/openrtb2/auction_ow_test.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http/httptest"
77
"testing"
88

9+
"github.com/golang/glog"
910
"github.com/prebid/prebid-server/v3/analytics/pubmatic"
1011
"github.com/prebid/prebid-server/v3/hooks/hookanalytics"
1112
"github.com/prebid/prebid-server/v3/hooks/hookexecution"
@@ -738,3 +739,147 @@ func TestUpdateResponseExtOW(t *testing.T) {
738739
})
739740
}
740741
}
742+
743+
func TestRemoveDefaultBidsFromSeatNonBid(t *testing.T) {
744+
t.Cleanup(func() { glog.Flush() })
745+
746+
tests := []struct {
747+
name string
748+
inputSB *openrtb_ext.SeatNonBidBuilder
749+
wantSB openrtb_ext.SeatNonBidBuilder
750+
wantAOSeatNonBid []openrtb_ext.SeatNonBid
751+
}{
752+
{
753+
name: "Empty_SeatNonBid",
754+
inputSB: &openrtb_ext.SeatNonBidBuilder{},
755+
wantSB: openrtb_ext.SeatNonBidBuilder{},
756+
wantAOSeatNonBid: nil,
757+
},
758+
{
759+
name: "SeatNonBid_with_default_bid",
760+
inputSB: &openrtb_ext.SeatNonBidBuilder{
761+
"seat1": {
762+
{ImpId: "imp1", StatusCode: 0},
763+
},
764+
},
765+
wantSB: openrtb_ext.SeatNonBidBuilder{
766+
"seat1": {
767+
{ImpId: "imp1", StatusCode: 0},
768+
},
769+
},
770+
wantAOSeatNonBid: []openrtb_ext.SeatNonBid{
771+
{Seat: "seat1", NonBid: []openrtb_ext.NonBid{
772+
{ImpId: "imp1", StatusCode: 0},
773+
}},
774+
},
775+
},
776+
{
777+
name: "Default_bid_and_bid_rejected_due_to_floors_for_impA",
778+
inputSB: &openrtb_ext.SeatNonBidBuilder{
779+
"seat1": {
780+
{ImpId: "impA", StatusCode: 0},
781+
{ImpId: "impA", StatusCode: 301},
782+
},
783+
},
784+
wantSB: openrtb_ext.SeatNonBidBuilder{
785+
"seat1": {
786+
{ImpId: "impA", StatusCode: 301},
787+
},
788+
},
789+
wantAOSeatNonBid: []openrtb_ext.SeatNonBid{
790+
{Seat: "seat1", NonBid: []openrtb_ext.NonBid{
791+
{ImpId: "impA", StatusCode: 301},
792+
}},
793+
},
794+
},
795+
{
796+
name: "Default_bid_and_bid_rejected_due_to_floors_for_multi_imp",
797+
inputSB: &openrtb_ext.SeatNonBidBuilder{
798+
"seat1": {
799+
{ImpId: "impA", StatusCode: 0},
800+
{ImpId: "impA", StatusCode: 301},
801+
{ImpId: "impB", StatusCode: 0},
802+
},
803+
},
804+
wantSB: openrtb_ext.SeatNonBidBuilder{
805+
"seat1": {
806+
{ImpId: "impA", StatusCode: 301},
807+
{ImpId: "impB", StatusCode: 0},
808+
},
809+
},
810+
wantAOSeatNonBid: []openrtb_ext.SeatNonBid{
811+
{Seat: "seat1", NonBid: []openrtb_ext.NonBid{
812+
{ImpId: "impA", StatusCode: 301},
813+
{ImpId: "impB", StatusCode: 0},
814+
}},
815+
},
816+
},
817+
{
818+
name: "Multiple_seats_with_all_bids_rejected_due_to_floors",
819+
inputSB: &openrtb_ext.SeatNonBidBuilder{
820+
"seat1": {
821+
{ImpId: "impA", StatusCode: 301},
822+
},
823+
"seat2": {
824+
{ImpId: "impA", StatusCode: 301},
825+
},
826+
},
827+
wantSB: openrtb_ext.SeatNonBidBuilder{
828+
"seat1": {
829+
{ImpId: "impA", StatusCode: 301},
830+
},
831+
"seat2": {
832+
{ImpId: "impA", StatusCode: 301},
833+
},
834+
},
835+
wantAOSeatNonBid: []openrtb_ext.SeatNonBid{
836+
{Seat: "seat1", NonBid: []openrtb_ext.NonBid{
837+
{ImpId: "impA", StatusCode: 301},
838+
}},
839+
{Seat: "seat2", NonBid: []openrtb_ext.NonBid{
840+
{ImpId: "impA", StatusCode: 301},
841+
}},
842+
},
843+
},
844+
{
845+
name: "Multiple_seats_independent",
846+
inputSB: &openrtb_ext.SeatNonBidBuilder{
847+
"seat1": {
848+
{ImpId: "impA", StatusCode: 0},
849+
{ImpId: "impB", StatusCode: 301},
850+
},
851+
"seat2": {
852+
{ImpId: "impA", StatusCode: 302},
853+
},
854+
},
855+
wantSB: openrtb_ext.SeatNonBidBuilder{
856+
"seat1": {
857+
{ImpId: "impA", StatusCode: 0},
858+
{ImpId: "impB", StatusCode: 301},
859+
},
860+
"seat2": {
861+
{ImpId: "impA", StatusCode: 302},
862+
},
863+
},
864+
wantAOSeatNonBid: []openrtb_ext.SeatNonBid{
865+
{Seat: "seat1", NonBid: []openrtb_ext.NonBid{
866+
{ImpId: "impA", StatusCode: 0},
867+
{ImpId: "impB", StatusCode: 301},
868+
}},
869+
{Seat: "seat2", NonBid: []openrtb_ext.NonBid{
870+
{ImpId: "impA", StatusCode: 302},
871+
}},
872+
},
873+
},
874+
}
875+
for _, tc := range tests {
876+
tc := tc
877+
t.Run(tc.name, func(t *testing.T) {
878+
ao := &analytics.AuctionObject{}
879+
removeDefaultBidsFromSeatNonBid(tc.inputSB, ao)
880+
881+
assert.Equal(t, &tc.wantSB, tc.inputSB, "SeatNonBidBuilder mismatch")
882+
assert.Equal(t, tc.wantAOSeatNonBid, ao.SeatNonBid, "AuctionObject.SeatNonBid mismatch")
883+
})
884+
}
885+
}

exchange/exchange_ow.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package exchange
22

33
import (
44
"context"
5+
"encoding/base64"
56
"encoding/json"
67
"errors"
78
"fmt"
@@ -433,9 +434,10 @@ func upadteOWDebugLog(requestExtPrebid *openrtb_ext.ExtRequestPrebid, debugLog *
433434

434435
func RecordVASTUnwrapperMetrics(metricsEngine metrics.MetricsEngine, ctx *unwrapmodels.UnwrapContext) {
435436
metricsEngine.RecordXMLParserResponseTime(ctx.Stats.ParserName, "unwrap", strconv.Itoa(ctx.Stats.WrapperCount), ctx.Stats.ResponseTime)
436-
if ctx.Stats.ErrorCode == 0 {
437-
metricsEngine.RecordXMLParserProcessingTime(ctx.Stats.ParserName, "unwrap", strconv.Itoa(ctx.Stats.WrapperCount), (ctx.Stats.ResponseTime - ctx.Stats.VASTAdTagURLFetchTime))
438-
} else {
437+
metricsEngine.RecordXMLParserProcessingTime(ctx.Stats.ParserName, "unwrap", strconv.Itoa(ctx.Stats.WrapperCount), (ctx.Stats.ResponseTime - ctx.Stats.VASTAdTagURLFetchTime))
438+
439+
if ctx.Stats.ErrorCode != 0 {
440+
openrtb_ext.XMLLogf(openrtb_ext.XMLLogFormat, "unwrap", base64.StdEncoding.EncodeToString(ctx.Vast))
439441
metricsEngine.RecordXMLParserError(ctx.Stats.ParserName, "unwrap", strconv.Itoa(ctx.Stats.WrapperCount))
440442
}
441443
}

modules/pubmatic/openwrap/beforevalidationhook.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -594,14 +594,18 @@ func (m OpenWrap) handleBeforeValidationHook(
594594
if len(impExt.GpId) == 0 {
595595
impExt.GpId = imp.TagID
596596
}
597+
}
598+
599+
if rCtx.Endpoint == models.EndpointAppLovinMax || rCtx.Endpoint == models.EndpointGoogleSDK {
597600
if payload.BidRequest.App != nil && payload.BidRequest.App.StoreURL == "" {
598601
var isValidAppStoreUrl bool
599-
if rCtx.AppLovinMax.AppStoreUrl, isValidAppStoreUrl = getProfileAppStoreUrl(rCtx); isValidAppStoreUrl {
602+
if rCtx.AppStoreUrl, isValidAppStoreUrl = getProfileAppStoreUrl(rCtx); isValidAppStoreUrl {
600603
m.updateSkadnSourceapp(rCtx, payload.BidRequest, impExt)
601604
}
602-
rCtx.PageURL = rCtx.AppLovinMax.AppStoreUrl
605+
rCtx.PageURL = rCtx.AppStoreUrl
603606
}
604607
}
608+
605609
impExt.Wrapper = nil
606610
impExt.Reward = nil
607611
impExt.Bidder = nil
@@ -754,10 +758,15 @@ func (m *OpenWrap) applyProfileChanges(rctx models.RequestCtx, bidRequest *openr
754758
}
755759

756760
if rctx.Endpoint == models.EndpointAppLovinMax {
757-
if rctx.AppLovinMax.AppStoreUrl != "" {
758-
bidRequest.App.StoreURL = rctx.AppLovinMax.AppStoreUrl
761+
if rctx.AppStoreUrl != "" {
762+
bidRequest.App.StoreURL = rctx.AppStoreUrl
759763
}
760764
}
765+
766+
if rctx.Endpoint == models.EndpointGoogleSDK && bidRequest.App != nil && bidRequest.App.StoreURL == "" && rctx.AppStoreUrl != "" {
767+
bidRequest.App.StoreURL = rctx.AppStoreUrl
768+
}
769+
761770
strictVastMode := models.GetVersionLevelPropertyFromPartnerConfig(rctx.PartnerConfigMap, models.StrictVastModeKey) == models.Enabled
762771
if strictVastMode {
763772
if rctx.NewReqExt == nil {
@@ -1355,7 +1364,6 @@ func updateImpVideoWithVideoConfig(imp *openrtb2.Imp, configObjInVideoConfig *mo
13551364
}
13561365

13571366
func updateAmpImpVideoWithDefault(imp *openrtb2.Imp) {
1358-
13591367
if imp.Video.W == nil {
13601368
imp.Video.W = getW(imp)
13611369
}
@@ -1439,12 +1447,12 @@ func getProfileAppStoreUrl(rctx models.RequestCtx) (string, bool) {
14391447
isValidAppStoreUrl := false
14401448
appStoreUrl := rctx.PartnerConfigMap[models.VersionLevelConfigID][models.AppStoreUrl]
14411449
if appStoreUrl == "" {
1442-
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [Error]: app store url not present in DB", rctx.PubID, rctx.ProfileID)
1450+
glog.Errorf("[PubID]: %d [ProfileID]: %d [Error]: app store url not present in DB", rctx.PubID, rctx.ProfileID)
14431451
return appStoreUrl, isValidAppStoreUrl
14441452
}
14451453
appStoreUrl = strings.TrimSpace(appStoreUrl)
14461454
if !isValidURL(appStoreUrl) {
1447-
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: Invalid app store url", rctx.PubID, rctx.ProfileID, appStoreUrl)
1455+
glog.Errorf("[PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: Invalid app store url", rctx.PubID, rctx.ProfileID, appStoreUrl)
14481456
return appStoreUrl, isValidAppStoreUrl
14491457
}
14501458
isValidAppStoreUrl = true
@@ -1457,19 +1465,19 @@ func (m *OpenWrap) updateSkadnSourceapp(rctx models.RequestCtx, bidRequest *open
14571465
}
14581466

14591467
if impExt == nil || impExt.SKAdnetwork == nil {
1460-
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [Error]: skadn is missing in imp.ext", rctx.PubID, rctx.ProfileID)
1468+
glog.Errorf("[PubID]: %d [ProfileID]: %d [Error]: skadn is missing in imp.ext", rctx.PubID, rctx.ProfileID)
14611469
return
14621470
}
14631471

1464-
itunesID := extractItunesIdFromAppStoreUrl(rctx.AppLovinMax.AppStoreUrl)
1472+
itunesID := extractItunesIdFromAppStoreUrl(rctx.AppStoreUrl)
14651473
if itunesID == "" {
14661474
m.metricEngine.RecordFailedParsingItuneID(rctx.PubIDStr, rctx.ProfileIDStr)
1467-
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: itunes id is missing in app store url", rctx.PubID, rctx.ProfileID, rctx.AppLovinMax.AppStoreUrl)
1475+
glog.Errorf("[PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: itunes id is missing in app store url", rctx.PubID, rctx.ProfileID, rctx.AppStoreUrl)
14681476
return
14691477
}
14701478

14711479
if updatedSKAdnetwork, err := jsonparser.Set(impExt.SKAdnetwork, []byte(strconv.Quote(itunesID)), "sourceapp"); err != nil {
1472-
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: %s", rctx.PubID, rctx.ProfileID, rctx.AppLovinMax.AppStoreUrl, err.Error())
1480+
glog.Errorf("[PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: %s", rctx.PubID, rctx.ProfileID, rctx.AppStoreUrl, err.Error())
14731481
} else {
14741482
impExt.SKAdnetwork = updatedSKAdnetwork
14751483
}

modules/pubmatic/openwrap/beforevalidationhook_test.go

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,10 +1901,8 @@ func TestOpenWrapApplyProfileChanges(t *testing.T) {
19011901
models.AppStoreUrl: "https://itunes.apple.com/us/app/angry-birds/id343200656",
19021902
},
19031903
},
1904-
Endpoint: models.EndpointAppLovinMax,
1905-
AppLovinMax: models.AppLovinMax{
1906-
AppStoreUrl: "https://itunes.apple.com/us/app/angry-birds/id343200656",
1907-
},
1904+
Endpoint: models.EndpointAppLovinMax,
1905+
AppStoreUrl: "https://itunes.apple.com/us/app/angry-birds/id343200656",
19081906
ImpBidCtx: map[string]models.ImpCtx{
19091907
"testImp1": {
19101908
NewExt: json.RawMessage(`{"skadn":{"sourceapp":"343200656"}}`),
@@ -7718,9 +7716,7 @@ func TestUpdateSkadnSourceapp(t *testing.T) {
77187716
models.AppStoreUrl: "https://apps.apple.com/app/id123456789",
77197717
},
77207718
},
7721-
AppLovinMax: models.AppLovinMax{
7722-
AppStoreUrl: "https://apps.apple.com/app/id123456789",
7723-
},
7719+
AppStoreUrl: "https://apps.apple.com/app/id123456789",
77247720
},
77257721
bidRequest: &openrtb2.BidRequest{
77267722
App: &openrtb2.App{},
@@ -7750,9 +7746,7 @@ func TestUpdateSkadnSourceapp(t *testing.T) {
77507746
models.AppStoreUrl: "https://apps.apple.com/app/id",
77517747
},
77527748
},
7753-
AppLovinMax: models.AppLovinMax{
7754-
AppStoreUrl: "https://apps.apple.com/app/id",
7755-
},
7749+
AppStoreUrl: "https://apps.apple.com/app/id",
77567750
},
77577751
bidRequest: &openrtb2.BidRequest{
77587752
App: &openrtb2.App{},
@@ -7778,9 +7772,7 @@ func TestUpdateSkadnSourceapp(t *testing.T) {
77787772
models.AppStoreUrl: "https://apps.apple.com/app/id123456789",
77797773
},
77807774
},
7781-
AppLovinMax: models.AppLovinMax{
7782-
AppStoreUrl: "https://apps.apple.com/app/id123456789",
7783-
},
7775+
AppStoreUrl: "https://apps.apple.com/app/id123456789",
77847776
},
77857777
bidRequest: &openrtb2.BidRequest{
77867778
App: &openrtb2.App{},
@@ -7807,9 +7799,7 @@ func TestUpdateSkadnSourceapp(t *testing.T) {
78077799
models.AppStoreUrl: "https://apps.apple.com/app/",
78087800
},
78097801
},
7810-
AppLovinMax: models.AppLovinMax{
7811-
AppStoreUrl: "https://apps.apple.com/app/",
7812-
},
7802+
AppStoreUrl: "https://apps.apple.com/app/",
78137803
PubIDStr: "5890",
78147804
ProfileIDStr: "1234",
78157805
},

modules/pubmatic/openwrap/models/nbr/codes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ const (
3636
InvalidResponseFormat openrtb3.NoBidReason = 618
3737
MissingOWRedirectURL openrtb3.NoBidReason = 619
3838
ResponseRejectedDSA openrtb3.NoBidReason = 620 // Response Rejected - DSA
39+
ResponseRejectedMissingParam openrtb3.NoBidReason = 621 // Response rejected due to missing required parameter
3940
)

modules/pubmatic/openwrap/models/openwrap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ type RequestCtx struct {
123123
ImpCountingMethodEnabledBidders map[string]struct{} // Bidders who have enabled ImpCountingMethod feature
124124
MultiFloors map[string]*MultiFloors // impression level floors
125125
GoogleSDK GoogleSDK
126+
AppStoreUrl string
126127

127128
// Adpod
128129
AdruleFlag bool
@@ -250,7 +251,6 @@ type FeatureData struct {
250251
type AppLovinMax struct {
251252
Reject bool
252253
MultiFloorsConfig MultiFloorsConfig
253-
AppStoreUrl string
254254
}
255255

256256
type MultiFloorsConfig struct {

0 commit comments

Comments
 (0)