Skip to content

Commit

Permalink
Support adapters to set seat for a bid prebid#2174
Browse files Browse the repository at this point in the history
  • Loading branch information
pm-nilesh-chate committed Jun 7, 2022
1 parent be2dc1c commit e73466c
Show file tree
Hide file tree
Showing 71 changed files with 1,803 additions and 326 deletions.
2 changes: 2 additions & 0 deletions adapters/adapterstest/test_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ type expectedBidResponse struct {
type expectedBid struct {
Bid json.RawMessage `json:"bid"`
Type string `json:"type"`
Seat string `json:"seat"`
}

// ---------------------------------------
Expand Down Expand Up @@ -314,6 +315,7 @@ func diffBids(t *testing.T, description string, actual *adapters.TypedBid, expec
return
}

assert.Equal(t, string(expected.Seat), string(actual.Seat), fmt.Sprintf(`%s.seat "%s" does not match expected "%s."`, description, string(actual.Seat), string(expected.Seat)))
assert.Equal(t, string(expected.Type), string(actual.BidType), fmt.Sprintf(`%s.type "%s" does not match expected "%s."`, description, string(actual.BidType), string(expected.Type)))
assert.NoError(t, diffOrtbBids(fmt.Sprintf("%s.bid", description), actual.Bid, expected.Bid))
}
Expand Down
2 changes: 2 additions & 0 deletions adapters/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,14 @@ func NewBidderResponse() *BidderResponse {
// TypedBid.BidType will become "response.seatbid[i].bid.ext.prebid.type" in the final OpenRTB response.
// TypedBid.BidVideo will become "response.seatbid[i].bid.ext.prebid.video" in the final OpenRTB response.
// TypedBid.DealPriority is optionally provided by adapters and used internally by the exchange to support deal targeted campaigns.
// TypedBid.Seat new seat under which the bid should pe placed. Default is adapter name
type TypedBid struct {
Bid *openrtb2.Bid
BidMeta *openrtb_ext.ExtBidPrebidMeta
BidType openrtb_ext.BidType
BidVideo *openrtb_ext.ExtBidPrebidVideo
DealPriority int
Seat openrtb_ext.BidderName
}

// RequestData and ResponseData exist so that prebid-server core code can implement its "debug" functionality
Expand Down
4 changes: 4 additions & 0 deletions adapters/pubmatic/pubmatic.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type PubmaticAdapter struct {
type pubmaticBidExt struct {
BidType *int `json:"BidType,omitempty"`
VideoCreativeInfo *pubmaticBidExtVideo `json:"video,omitempty"`
Marketplace string `json:"marketplace,omitempty"`
}

type pubmaticWrapperExt struct {
Expand Down Expand Up @@ -390,9 +391,11 @@ func (a *PubmaticAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externa
bid.Cat = bid.Cat[0:1]
}

seat := ""
var bidExt *pubmaticBidExt
bidType := openrtb_ext.BidTypeBanner
if err := json.Unmarshal(bid.Ext, &bidExt); err == nil && bidExt != nil {
seat = bidExt.Marketplace
if bidExt.VideoCreativeInfo != nil && bidExt.VideoCreativeInfo.Duration != nil {
impVideo.Duration = *bidExt.VideoCreativeInfo.Duration
}
Expand All @@ -402,6 +405,7 @@ func (a *PubmaticAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externa
Bid: &bid,
BidType: bidType,
BidVideo: impVideo,
Seat: openrtb_ext.BidderName(seat),
})

}
Expand Down
195 changes: 195 additions & 0 deletions adapters/pubmatic/pubmatictest/supplemental/extra-bid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
{
"mockBidRequest": {
"id": "test-request-id",
"imp": [{
"id": "test-imp-id",
"banner": {
"format": [{
"w": 300,
"h": 250
}]
},
"ext": {
"bidder": {
"adSlot": "AdTag_Div1@300x250",
"publisherId": "999",
"keywords": [{
"key": "pmZoneID",
"value": ["Zone1", "Zone2"]
},
{
"key": "preference",
"value": ["sports", "movies"]
}
],
"kadfloor": "0.12",
"wrapper": {
"version": 1,
"profile": 5123
}
}
}
}],
"device":{
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
},
"ext": {
"prebid": {
"bidderparams": {
"acat": ["drg","dlu","ssr"]
}
}
},
"site": {
"id": "siteID",
"publisher": {
"id": "1234"
}
}
},

"httpCalls": [
{
"expectedRequest": {
"uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server",
"body": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"tagid":"AdTag_Div1",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
],
"h": 250,
"w": 300
},
"bidfloor": 0.12,
"ext": {
"pmZoneId": "Zone1,Zone2",
"preference": "sports,movies"
}
}
],
"device":{
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
},
"site": {
"id": "siteID",
"publisher": {
"id": "999"
}
},
"ext": {
"wrapper": {
"profile": 5123,
"version":1
},
"acat": ["drg","dlu","ssr"]
}
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id",
"seatbid": [
{
"seat": "958",
"bid": [{
"id": "7706636740145184841",
"impid": "test-imp-id",
"price": 0.500000,
"adid": "29681110",
"adm": "some-test-ad",
"adomain": ["pubmatic.com"],
"crid": "29681110",
"h": 250,
"w": 300,
"dealid":"test deal",
"ext": {
"dspid": 6,
"deal_channel": 1
}
}]
},
{
"seat": "123",
"bid": [{
"id": "1814876ae93d31",
"impid": "test-imp-id",
"price": 0.500000,
"adid": "29681110",
"adm": "some-test-ad",
"adomain": ["mystartab.com"],
"crid": "29681110",
"h": 250,
"w": 300,
"dealid":"test deal",
"ext": {
"dspid": 6,
"deal_channel": 1,
"marketplace": "groupm"
}
}]
}
],
"bidid": "5778926625248726496",
"cur": "USD"
}
}
}
],

"expectedBidResponses": [
{
"currency": "USD",
"bids": [
{
"bid": {
"id": "7706636740145184841",
"impid": "test-imp-id",
"price": 0.5,
"adid": "29681110",
"adm": "some-test-ad",
"adomain": ["pubmatic.com"],
"crid": "29681110",
"w": 300,
"h": 250,
"dealid":"test deal",
"ext": {
"dspid": 6,
"deal_channel": 1
}
},
"type": "banner"
},
{
"bid": {
"id": "1814876ae93d31",
"impid": "test-imp-id",
"price": 0.5,
"adid": "29681110",
"adm": "some-test-ad",
"adomain": ["mystartab.com"],
"crid": "29681110",
"w": 300,
"h": 250,
"dealid":"test deal",
"ext": {
"dspid": 6,
"deal_channel": 1,
"marketplace": "groupm"
}
},
"type": "banner",
"seat": "groupm"
}
]
}
]
}
72 changes: 61 additions & 11 deletions config/accounts.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"fmt"

"github.com/prebid/go-gdpr/consentconstants"
"github.com/prebid/prebid-server/openrtb_ext"
)
Expand All @@ -18,17 +20,18 @@ const (

// Account represents a publisher account configuration
type Account struct {
ID string `mapstructure:"id" json:"id"`
Disabled bool `mapstructure:"disabled" json:"disabled"`
CacheTTL DefaultTTLs `mapstructure:"cache_ttl" json:"cache_ttl"`
EventsEnabled bool `mapstructure:"events_enabled" json:"events_enabled"`
CCPA AccountCCPA `mapstructure:"ccpa" json:"ccpa"`
GDPR AccountGDPR `mapstructure:"gdpr" json:"gdpr"`
DebugAllow bool `mapstructure:"debug_allow" json:"debug_allow"`
DefaultIntegration string `mapstructure:"default_integration" json:"default_integration"`
CookieSync CookieSync `mapstructure:"cookie_sync" json:"cookie_sync"`
Events Events `mapstructure:"events" json:"events"` // Don't enable this feature. It is still under developmment - https://github.com/prebid/prebid-server/issues/1725
TruncateTargetAttribute *int `mapstructure:"truncate_target_attr" json:"truncate_target_attr"`
ID string `mapstructure:"id" json:"id"`
Disabled bool `mapstructure:"disabled" json:"disabled"`
CacheTTL DefaultTTLs `mapstructure:"cache_ttl" json:"cache_ttl"`
EventsEnabled bool `mapstructure:"events_enabled" json:"events_enabled"`
CCPA AccountCCPA `mapstructure:"ccpa" json:"ccpa"`
GDPR AccountGDPR `mapstructure:"gdpr" json:"gdpr"`
DebugAllow bool `mapstructure:"debug_allow" json:"debug_allow"`
DefaultIntegration string `mapstructure:"default_integration" json:"default_integration"`
CookieSync CookieSync `mapstructure:"cookie_sync" json:"cookie_sync"`
Events Events `mapstructure:"events" json:"events"` // Don't enable this feature. It is still under developmment - https://github.com/prebid/prebid-server/issues/1725
TruncateTargetAttribute *int `mapstructure:"truncate_target_attr" json:"truncate_target_attr"`
AlternateBidderCodes AlternateBidderCodes `mapstructure:"alternatebiddercodes" json:"alternatebiddercodes"`
}

// CookieSync represents the account-level defaults for the cookie sync endpoint.
Expand Down Expand Up @@ -222,3 +225,50 @@ func (a *AccountIntegration) GetByIntegrationType(integrationType IntegrationTyp

return integrationEnabled
}

type AlternateBidderCodes struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
Adapters map[string]AdapterAlternateBidderCodes `mapstructure:"adapters" json:"adapters"`
}

type AdapterAlternateBidderCodes struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
AllowedBidderCodes []string `mapstructure:"allowedbiddercodes" json:"allowedbiddercodes"`
}

func (account *AlternateBidderCodes) IsValidBidderCode(bidder, alternateBidder string) (bool, error) {
const ErrAlternateBidderNotDefined = "alternateBidderCodes not defined for adapter %q, rejecting bids for %q"

if alternateBidder == "" || bidder == alternateBidder {
return true, nil
}

if !account.Enabled {
return false, nil
}

if account.Adapters == nil {
return false, fmt.Errorf(ErrAlternateBidderNotDefined, bidder, alternateBidder)
}

adapterCfg, ok := account.Adapters[bidder]
if !ok {
return false, fmt.Errorf(ErrAlternateBidderNotDefined, bidder, alternateBidder)
}

if !adapterCfg.Enabled || len(adapterCfg.AllowedBidderCodes) == 0 {
return false, fmt.Errorf("alternateBidderCodes disabled for %q, rejecting bids for %q", bidder, alternateBidder)
}

if adapterCfg.AllowedBidderCodes[0] == "*" {
return true, nil
}

for _, code := range adapterCfg.AllowedBidderCodes {
if alternateBidder == code {
return true, nil
}
}

return false, fmt.Errorf("invalid biddercode %q sent by adapter %q", alternateBidder, bidder)
}
Loading

0 comments on commit e73466c

Please sign in to comment.