Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UOE-11191: Refactor: consume StoreURL from New portal UI and forward appstoreurl and appsource for applovinmax #925

Merged
merged 6 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions modules/pubmatic/openwrap/beforevalidationhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,10 @@ func (m OpenWrap) handleBeforeValidationHook(
}

if rCtx.Endpoint == models.EndpointAppLovinMax && payload.BidRequest.App != nil && payload.BidRequest.App.StoreURL == "" {
rCtx.AppLovinMax.AppStoreUrl = getProfileAppStoreUrlAndUpdateItunesID(rCtx, payload.BidRequest, impExt)
var isValidAppStoreUrl bool
if rCtx.AppLovinMax.AppStoreUrl, isValidAppStoreUrl = getProfileAppStoreUrl(rCtx); isValidAppStoreUrl {
m.updateSkadnSourceapp(rCtx, payload.BidRequest, impExt)
}
rCtx.PageURL = rCtx.AppLovinMax.AppStoreUrl
}
impExt.Wrapper = nil
Expand Down Expand Up @@ -1344,36 +1347,44 @@ func isValidURL(urlVal string) bool {
return validator.IsRequestURL(urlVal) && validator.IsURL(urlVal)
}

func getProfileAppStoreUrlAndUpdateItunesID(rctx models.RequestCtx, bidRequest *openrtb2.BidRequest, impExt *models.ImpExtension) string {
func getProfileAppStoreUrl(rctx models.RequestCtx) (string, bool) {
isValidAppStoreUrl := false
appStoreUrl := rctx.PartnerConfigMap[models.VersionLevelConfigID][models.AppStoreUrl]
if appStoreUrl == "" {
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [Error]: app storeurl not present in DB", rctx.PubID, rctx.ProfileID)
return appStoreUrl
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [Error]: app store url not present in DB", rctx.PubID, rctx.ProfileID)
return appStoreUrl, isValidAppStoreUrl
}
appStoreUrl = strings.TrimSpace(appStoreUrl)
if !isValidURL(appStoreUrl) {
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: Invalid app storeurl", rctx.PubID, rctx.ProfileID, appStoreUrl)
return appStoreUrl
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: Invalid app store url", rctx.PubID, rctx.ProfileID, appStoreUrl)
return appStoreUrl, isValidAppStoreUrl
}
var err error
if bidRequest.Device != nil && strings.ToLower(bidRequest.Device.OS) == "ios" {
//no multiple imp supported for AppLovinMax
if impExt != nil {
if impExt.SKAdnetwork == nil {
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [Error]: skadn is missing in imp.ext", rctx.PubID, rctx.ProfileID, appStoreUrl)
return appStoreUrl
}
var itunesID string
if itunesID = extractItunesIdFromAppStoreUrl(appStoreUrl); itunesID == "" {
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: itunes id is missing in app store url", rctx.PubID, rctx.ProfileID, appStoreUrl)
return appStoreUrl
}
if impExt.SKAdnetwork, err = jsonparser.Set(impExt.SKAdnetwork, []byte(strconv.Quote(itunesID)), "sourceapp"); err != nil {
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: %s", rctx.PubID, rctx.ProfileID, appStoreUrl, err.Error())
}
}
isValidAppStoreUrl = true
return appStoreUrl, isValidAppStoreUrl
}

func (m *OpenWrap) updateSkadnSourceapp(rctx models.RequestCtx, bidRequest *openrtb2.BidRequest, impExt *models.ImpExtension) {
if bidRequest.Device == nil || strings.ToLower(bidRequest.Device.OS) != "ios" {
return
}

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

itunesID := extractItunesIdFromAppStoreUrl(rctx.AppLovinMax.AppStoreUrl)
if itunesID == "" {
m.metricEngine.RecordFailedParsingItuneID(rctx.PubIDStr, rctx.ProfileIDStr)
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)
return
}

if updatedSKAdnetwork, err := jsonparser.Set(impExt.SKAdnetwork, []byte(strconv.Quote(itunesID)), "sourceapp"); err != nil {
glog.Errorf("[AppLovinMax] [PubID]: %d [ProfileID]: %d [AppStoreUrl]: %s [Error]: %s", rctx.PubID, rctx.ProfileID, rctx.AppLovinMax.AppStoreUrl, err.Error())
} else {
impExt.SKAdnetwork = updatedSKAdnetwork
}
return appStoreUrl
}

func extractItunesIdFromAppStoreUrl(url string) string {
Expand Down
123 changes: 100 additions & 23 deletions modules/pubmatic/openwrap/beforevalidationhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6572,37 +6572,83 @@ func TestSetImpBidFloorParams(t *testing.T) {
}
}

func TestUpdateProfileAppStoreUrl(t *testing.T) {
func TestGetProfileAppStoreUrl(t *testing.T) {
type args struct {
rctx models.RequestCtx
}
tests := []struct {
name string
rctx models.RequestCtx
bidRequest *openrtb2.BidRequest
impExt *models.ImpExtension
wantAppStoreURL string
wantSourceApp string
name string
args args
want string
want1 bool
}{
{
name: "AppStoreUrl missing in DB",
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {},
args: args{
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {},
},
},
},
bidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}},
wantAppStoreURL: "",
want: "",
want1: false,
},
{
name: "Invalid AppStoreUrl",
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {
models.AppStoreUrl: "invalid-url",
args: args{
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {
models.AppStoreUrl: "invalid-url",
},
},
},
},
want: "invalid-url",
want1: false,
},
{
name: "Valid AppStoreUrl",
args: args{
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {
models.AppStoreUrl: "https://apps.apple.com/app/id123456789",
},
},
},
},
bidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}},
wantAppStoreURL: "invalid-url",
want: "https://apps.apple.com/app/id123456789",
want1: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := getProfileAppStoreUrl(tt.args.rctx)
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.want1, got1)
})
}
}

func TestUpdateSkadnSourceapp(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

type feilds struct {
m *OpenWrap
}
tests := []struct {
name string
rctx models.RequestCtx
bidRequest *openrtb2.BidRequest
impExt *models.ImpExtension
wantAppStoreURL string
wantSourceApp string
fe feilds
setup func() *mock_metrics.MockMetricsEngine
}{
{
name: "Valid AppStoreUrl os is ios and SKAdnetwork is present in imp.ext",
rctx: models.RequestCtx{
Expand All @@ -6611,6 +6657,9 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
models.AppStoreUrl: "https://apps.apple.com/app/id123456789",
},
},
AppLovinMax: models.AppLovinMax{
AppStoreUrl: "https://apps.apple.com/app/id123456789",
},
},
bidRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Expand All @@ -6626,6 +6675,9 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
impExt: &models.ImpExtension{
SKAdnetwork: json.RawMessage(`{}`),
},
setup: func() *mock_metrics.MockMetricsEngine {
return mock_metrics.NewMockMetricsEngine(ctrl)
},
wantAppStoreURL: "https://apps.apple.com/app/id123456789",
wantSourceApp: "123456789",
},
Expand All @@ -6634,9 +6686,12 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {
models.AppStoreUrl: "https://apps.apple.com/app/id123456789",
models.AppStoreUrl: "https://apps.apple.com/app/id",
},
},
AppLovinMax: models.AppLovinMax{
AppStoreUrl: "https://apps.apple.com/app/id",
},
},
bidRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Expand All @@ -6649,7 +6704,10 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
},
},
},
wantAppStoreURL: "https://apps.apple.com/app/id123456789",
setup: func() *mock_metrics.MockMetricsEngine {
return mock_metrics.NewMockMetricsEngine(ctrl)
},
wantAppStoreURL: "https://apps.apple.com/app/id",
},
{
name: "Valid AppStoreUrl os is ios but SKAdnetwork missing in imp.ext",
Expand All @@ -6659,6 +6717,9 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
models.AppStoreUrl: "https://apps.apple.com/app/id123456789",
},
},
AppLovinMax: models.AppLovinMax{
AppStoreUrl: "https://apps.apple.com/app/id123456789",
},
},
bidRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Expand All @@ -6671,17 +6732,25 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
},
},
},
setup: func() *mock_metrics.MockMetricsEngine {
return mock_metrics.NewMockMetricsEngine(ctrl)
},
impExt: &models.ImpExtension{},
wantAppStoreURL: "https://apps.apple.com/app/id123456789",
},
{
name: "Valid AppStoreUrl os is ios but Itunes ID missing in AppStoreUrl",
name: "Valid AppStoreUrl os is ios but Itunes ID missing in AppStoreUrl(url is of Android)",
rctx: models.RequestCtx{
PartnerConfigMap: map[int]map[string]string{
models.VersionLevelConfigID: {
models.AppStoreUrl: "https://apps.apple.com/app/",
},
},
AppLovinMax: models.AppLovinMax{
AppStoreUrl: "https://apps.apple.com/app/",
},
PubIDStr: "5890",
ProfileIDStr: "1234",
},
bidRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Expand All @@ -6694,6 +6763,11 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {
},
},
},
setup: func() *mock_metrics.MockMetricsEngine {
mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
mockEngine.EXPECT().RecordFailedParsingItuneID("5890", "1234")
return mockEngine
},
impExt: &models.ImpExtension{
SKAdnetwork: json.RawMessage(`{}`),
},
Expand All @@ -6703,8 +6777,11 @@ func TestUpdateProfileAppStoreUrl(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotAppStoreURL := getProfileAppStoreUrlAndUpdateItunesID(tt.rctx, tt.bidRequest, tt.impExt)
assert.Equal(t, tt.wantAppStoreURL, gotAppStoreURL)
metricsEngine := tt.setup()
tt.fe.m = &OpenWrap{
metricEngine: metricsEngine,
}
tt.fe.m.updateSkadnSourceapp(tt.rctx, tt.bidRequest, tt.impExt)
if tt.impExt != nil {
if tt.impExt.SKAdnetwork != nil {
var skAdnetwork map[string]interface{}
Expand Down
7 changes: 7 additions & 0 deletions modules/pubmatic/openwrap/metrics/config/multimetrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,3 +529,10 @@ func (me *MultiMetricsEngine) RecordSignalDataStatus(pubid, profileid, signalTyp
thisME.RecordSignalDataStatus(pubid, profileid, signalType)
}
}

// RecordFailedParsingItuneID record failed parsing itune id
func (me *MultiMetricsEngine) RecordFailedParsingItuneID(pubId, profId string) {
for _, thisME := range *me {
thisME.RecordFailedParsingItuneID(pubId, profId)
}
}
3 changes: 3 additions & 0 deletions modules/pubmatic/openwrap/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,7 @@ type MetricsEngine interface {
//VMAP-adrule
RecordAdruleEnabled(pubId, profId string)
RecordAdruleValidationFailure(pubId, profId string)

//AppLovinMax metrics
RecordFailedParsingItuneID(pubId, profId string)
}
12 changes: 12 additions & 0 deletions modules/pubmatic/openwrap/metrics/mock/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ type Metrics struct {
//VMAP adrule
pubProfAdruleEnabled *prometheus.CounterVec
pubProfAdruleValidationfailure *prometheus.CounterVec

//ApplovinMax
failedParsingItuneId *prometheus.CounterVec
}

const (
Expand Down Expand Up @@ -360,6 +363,12 @@ func newMetrics(cfg *config.PrometheusMetrics, promRegistry *prometheus.Registry
[]string{pubIdLabel, profileIDLabel},
)

metrics.failedParsingItuneId = newCounter(cfg, promRegistry,
"failed_parsing_itune_id",
"Count of failed parsing itune id",
[]string{pubIdLabel, profileIDLabel},
)

newSSHBMetrics(&metrics, cfg, promRegistry)

return &metrics
Expand Down Expand Up @@ -599,6 +608,14 @@ func (m *Metrics) RecordSignalDataStatus(pubid, profileid, signalType string) {
}).Inc()
}

func (m *Metrics) RecordFailedParsingItuneID(pubId, profId string) {
m.failedParsingItuneId.With(prometheus.Labels{
pubIDLabel: pubId,
profileIDLabel: profId,
}).Inc()

}

// TODO - really need ?
func (m *Metrics) RecordPBSAuctionRequestsStats() {}

Expand Down
1 change: 1 addition & 0 deletions modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,4 @@ func (st *StatsTCP) RecordSignalDataStatus(pubid, profileid, signalType string)
func (st *StatsTCP) RecordPrebidCacheRequestTime(success bool, length time.Duration) {}
func (st *StatsTCP) RecordPrebidAuctionBidResponse(publisher string, partnerName string, bidderCode string, adapterCode string) {
}
func (st *StatsTCP) RecordFailedParsingItuneID(pubId, profId string) {}
Loading