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

DOOH support #2758

Merged
merged 11 commits into from
Sep 20, 2023
24 changes: 20 additions & 4 deletions adapters/infoawarebidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// media types defined in the static/bidder-info/{bidder}.yaml file.
//
// It adjusts incoming requests in the following ways:
// 1. If App or Site traffic is not supported by the info file, then requests from
// 1. If App, Site or DOOH traffic is not supported by the info file, then requests from
// those sources will be rejected before the delegate is called.
// 2. If a given MediaType is not supported for the platform, then it will be set
// to nil before the request is forwarded to the delegate.
Expand All @@ -24,7 +24,7 @@ type InfoAwareBidder struct {
info parsedBidderInfo
}

// BuildInfoAwareBidder wraps a bidder to enforce site, app, and media type support.
// BuildInfoAwareBidder wraps a bidder to enforce inventory {site, app, dooh} and media type support.
func BuildInfoAwareBidder(bidder Bidder, info config.BidderInfo) Bidder {
return &InfoAwareBidder{
Bidder: bidder,
Expand All @@ -47,6 +47,12 @@ func (i *InfoAwareBidder) MakeRequests(request *openrtb2.BidRequest, reqInfo *Ex
}
allowedMediaTypes = i.info.app
}
if request.DOOH != nil {
if !i.info.dooh.enabled {
return nil, []error{&errortypes.Warning{Message: "this bidder does not support dooh requests"}}
}
allowedMediaTypes = i.info.dooh
}

// Filtering imps is quite expensive (array filter with large, non-pointer elements)... but should be rare,
// because it only happens if the publisher makes a really bad request.
Expand Down Expand Up @@ -136,6 +142,7 @@ func filterImps(imps []openrtb2.Imp, numToFilter int) ([]openrtb2.Imp, []error)
type parsedBidderInfo struct {
app parsedSupports
site parsedSupports
dooh parsedSupports
}

type parsedSupports struct {
Expand All @@ -148,13 +155,22 @@ type parsedSupports struct {

func parseBidderInfo(info config.BidderInfo) parsedBidderInfo {
var parsedInfo parsedBidderInfo
if info.Capabilities != nil && info.Capabilities.App != nil {

if info.Capabilities == nil {
return parsedInfo
}

if info.Capabilities.App != nil {
parsedInfo.app.enabled = true
parsedInfo.app.banner, parsedInfo.app.video, parsedInfo.app.audio, parsedInfo.app.native = parseAllowedTypes(info.Capabilities.App.MediaTypes)
}
if info.Capabilities != nil && info.Capabilities.Site != nil {
if info.Capabilities.Site != nil {
parsedInfo.site.enabled = true
parsedInfo.site.banner, parsedInfo.site.video, parsedInfo.site.audio, parsedInfo.site.native = parseAllowedTypes(info.Capabilities.Site.MediaTypes)
}
if info.Capabilities.DOOH != nil {
parsedInfo.dooh.enabled = true
parsedInfo.dooh.banner, parsedInfo.dooh.video, parsedInfo.dooh.audio, parsedInfo.dooh.native = parseAllowedTypes(info.Capabilities.DOOH.MediaTypes)
}
return parsedInfo
}
30 changes: 27 additions & 3 deletions adapters/infoawarebidder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/prebid/prebid-server/errortypes"
"github.com/prebid/prebid-server/openrtb_ext"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAppNotSupported(t *testing.T) {
Expand Down Expand Up @@ -56,6 +57,26 @@ func TestSiteNotSupported(t *testing.T) {
assert.Len(t, bids, 0)
}

func TestDOOHNotSupported(t *testing.T) {
bidder := &mockBidder{}
info := config.BidderInfo{
Capabilities: &config.CapabilitiesInfo{
Site: &config.PlatformInfo{
MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner},
},
},
}
constrained := adapters.BuildInfoAwareBidder(bidder, info)
bids, errs := constrained.MakeRequests(&openrtb2.BidRequest{
Imp: []openrtb2.Imp{{ID: "imp-1", Banner: &openrtb2.Banner{}}},
DOOH: &openrtb2.DOOH{},
}, &adapters.ExtraRequestInfo{})
require.Len(t, errs, 1)
assert.EqualError(t, errs[0], "this bidder does not support dooh requests")
assert.IsType(t, &errortypes.Warning{}, errs[0])
assert.Len(t, bids, 0)
}

minaguib marked this conversation as resolved.
Show resolved Hide resolved
func TestImpFiltering(t *testing.T) {
bidder := &mockBidder{}
info := config.BidderInfo{
Expand All @@ -66,6 +87,9 @@ func TestImpFiltering(t *testing.T) {
App: &config.PlatformInfo{
MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner},
},
DOOH: &config.PlatformInfo{
MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeNative},
},
},
}

Expand Down Expand Up @@ -153,10 +177,10 @@ func TestImpFiltering(t *testing.T) {
description: "All imps with correct media type, MakeRequest() call expected",
inBidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp-1", Video: &openrtb2.Video{}},
{ID: "imp-2", Video: &openrtb2.Video{}},
{ID: "imp-1", Native: &openrtb2.Native{}},
{ID: "imp-2", Native: &openrtb2.Native{}},
},
Site: &openrtb2.Site{},
DOOH: &openrtb2.DOOH{},
},
expectedErrors: nil,
expectedImpLen: 2,
Expand Down
6 changes: 5 additions & 1 deletion config/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
ChannelApp ChannelType = "app"
ChannelVideo ChannelType = "video"
ChannelWeb ChannelType = "web"
ChannelDOOH ChannelType = "dooh"
)

// Account represents a publisher account configuration
Expand Down Expand Up @@ -247,6 +248,7 @@ type AccountChannel struct {
App *bool `mapstructure:"app" json:"app,omitempty"`
Video *bool `mapstructure:"video" json:"video,omitempty"`
Web *bool `mapstructure:"web" json:"web,omitempty"`
DOOH *bool `mapstructure:"dooh" json:"dooh,omitempty"`
}

// GetByChannelType looks up the account integration enabled setting for the specified channel type
Expand All @@ -262,6 +264,8 @@ func (a *AccountChannel) GetByChannelType(channelType ChannelType) *bool {
channelEnabled = a.Video
case ChannelWeb:
channelEnabled = a.Web
case ChannelDOOH:
channelEnabled = a.DOOH
}

return channelEnabled
Expand Down Expand Up @@ -292,7 +296,7 @@ func (m AccountModules) ModuleConfig(id string) (json.RawMessage, error) {
}

func (a *AccountChannel) IsSet() bool {
return a.AMP != nil || a.App != nil || a.Video != nil || a.Web != nil
return a.AMP != nil || a.App != nil || a.Video != nil || a.Web != nil || a.DOOH != nil
}

type AccountPrivacy struct {
Expand Down
21 changes: 20 additions & 1 deletion config/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ func TestAccountChannelGetByChannelType(t *testing.T) {
giveAppEnabled *bool
giveVideoEnabled *bool
giveWebEnabled *bool
giveDOOHEnabled *bool
giveChannelType ChannelType
wantEnabled *bool
}{
Expand Down Expand Up @@ -276,6 +277,23 @@ func TestAccountChannelGetByChannelType(t *testing.T) {
giveChannelType: ChannelWeb,
wantEnabled: &trueValue,
},
{
description: "DOOH channel setting unspecified, returns nil",
giveChannelType: ChannelDOOH,
wantEnabled: nil,
},
{
description: "DOOH channel disabled, returns false",
giveDOOHEnabled: &falseValue,
giveChannelType: ChannelDOOH,
wantEnabled: &falseValue,
},
{
description: "DOOH channel enabled, returns true",
giveDOOHEnabled: &trueValue,
giveChannelType: ChannelDOOH,
wantEnabled: &trueValue,
},
}

for _, tt := range tests {
Expand All @@ -284,6 +302,7 @@ func TestAccountChannelGetByChannelType(t *testing.T) {
App: tt.giveAppEnabled,
Video: tt.giveVideoEnabled,
Web: tt.giveWebEnabled,
DOOH: tt.giveDOOHEnabled,
}

result := accountChannel.GetByChannelType(tt.giveChannelType)
Expand Down Expand Up @@ -836,7 +855,7 @@ func TestAccountChannelIsSet(t *testing.T) {
}{
{
name: "AccountChannelSetAllFields",
givenAccountChannel: &AccountChannel{AMP: &trueBool, App: &falseBool, Video: &falseBool, Web: &falseBool},
givenAccountChannel: &AccountChannel{AMP: &trueBool, App: &falseBool, Video: &falseBool, Web: &falseBool, DOOH: &falseBool},
expected: true,
},
{
Expand Down
24 changes: 20 additions & 4 deletions config/bidderinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type MaintainerInfo struct {
type CapabilitiesInfo struct {
App *PlatformInfo `yaml:"app" mapstructure:"app"`
Site *PlatformInfo `yaml:"site" mapstructure:"site"`
DOOH *PlatformInfo `yaml:"dooh" mapstructure:"dooh"`
}

// PlatformInfo specifies the supported media types for a bidder.
Expand Down Expand Up @@ -461,7 +462,9 @@ func validateAliasCapabilities(aliasBidderInfo BidderInfo, infos BidderInfos, bi
return fmt.Errorf("capabilities for alias: %s should be a subset of capabilities for parent bidder: %s", bidderName, aliasBidderInfo.AliasOf)
}

if (aliasBidderInfo.Capabilities.App != nil && parentBidder.Capabilities.App == nil) || (aliasBidderInfo.Capabilities.Site != nil && parentBidder.Capabilities.Site == nil) {
if (aliasBidderInfo.Capabilities.App != nil && parentBidder.Capabilities.App == nil) ||
(aliasBidderInfo.Capabilities.Site != nil && parentBidder.Capabilities.Site == nil) ||
(aliasBidderInfo.Capabilities.DOOH != nil && parentBidder.Capabilities.DOOH == nil) {
return fmt.Errorf("capabilities for alias: %s should be a subset of capabilities for parent bidder: %s", bidderName, aliasBidderInfo.AliasOf)
}

Expand All @@ -476,6 +479,12 @@ func validateAliasCapabilities(aliasBidderInfo BidderInfo, infos BidderInfos, bi
return err
}
}

if aliasBidderInfo.Capabilities.DOOH != nil && parentBidder.Capabilities.DOOH != nil {
if err := isAliasPlatformInfoSubsetOfParent(*parentBidder.Capabilities.DOOH, *aliasBidderInfo.Capabilities.DOOH, bidderName, aliasBidderInfo.AliasOf); err != nil {
return err
}
}
}

return nil
Expand All @@ -501,8 +510,8 @@ func validateCapabilities(info *CapabilitiesInfo, bidderName string) error {
return fmt.Errorf("missing required field: capabilities for adapter: %s", bidderName)
}

if info.App == nil && info.Site == nil {
return fmt.Errorf("at least one of capabilities.site or capabilities.app must exist for adapter: %s", bidderName)
if info.App == nil && info.Site == nil && info.DOOH == nil {
return fmt.Errorf("at least one of capabilities.site, capabilities.app, or capabilities.dooh must exist for adapter: %s", bidderName)
}

if info.App != nil {
Expand All @@ -513,9 +522,16 @@ func validateCapabilities(info *CapabilitiesInfo, bidderName string) error {

if info.Site != nil {
if err := validatePlatformInfo(info.Site); err != nil {
return fmt.Errorf("capabilities.site failed validation: %v, for adapter: %s", err, bidderName)
return fmt.Errorf("capabilities.site failed validation: %v for adapter: %s", err, bidderName)
}
}

if info.DOOH != nil {
if err := validatePlatformInfo(info.DOOH); err != nil {
return fmt.Errorf("capabilities.dooh failed validation: %v for adapter: %s", err, bidderName)
}
}

return nil
}

Expand Down
Loading