Skip to content

Commit

Permalink
Add nova multicall (prebid#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
Peiling-Ding committed Nov 8, 2023
1 parent eda2630 commit 7a72c37
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 21 deletions.
9 changes: 8 additions & 1 deletion pkg/modules/multi_call/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import (
type builder struct{}

func (b builder) Build(rawConfig json.RawMessage, deps moduledeps.ModuleDeps) (interface{}, error) {
return &multi.Module{}, nil
cfg, err := multi.NewConfig(rawConfig)
if err != nil {
return &multi.Module{}, err
} else {
return &multi.Module{
Mappings: cfg.Mappings,
}, nil
}
}

var Builder builder
23 changes: 23 additions & 0 deletions pkg/modules/multi_call/module/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package multi

import (
"encoding/json"
"fmt"
)

func NewConfig(data json.RawMessage) (MultiCallConfig, error) {
var cfg MultiCallConfig
if err := json.Unmarshal(data, &cfg); err != nil {
return cfg, fmt.Errorf("failed to parse config: %s", err)
}
return cfg, nil
}

type MultiCallConfig struct {
Mappings []MultiCallMapping `json:"mappings"`
}

type MultiCallMapping struct {
Prefix string `json:"prefix"`
Bidder string `json:"bidder"`
}
83 changes: 63 additions & 20 deletions pkg/modules/multi_call/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,58 +7,101 @@ import (
"strings"

"github.com/golang/glog"
"github.com/prebid/openrtb/v19/openrtb2"
"github.com/prebid/prebid-server/hooks/hookstage"
"github.com/prebid/prebid-server/openrtb_ext"
)

type Module struct{}
type Module struct {
Mappings []MultiCallMapping
}

var PREFIXES = []string{"hb_bidder", "hb_cache_host", "hb_cache_id", "hb_cache_path", "hb_env", "hb_pb"}

var audienceNetwork = string(openrtb_ext.BidderAudienceNetwork)

// This hook change the `msp_fb_x` back to `audienceNetwork` so that client can render ads
// This hook changes the response returned by multi-call bidders. In following example, all
// bidders with prefix `msp_fb_` are changed back to `audienceNetwork`:
// Input:
//
// "targeting": {
// "hb_bidder": "msp_fb_alpha",
// "hb_bidder_msp_fb_alp": "msp_fb_alpha",
// "hb_cache_host": "prebid-cache.newsbreak.com",
// "hb_cache_host_msp_fb": "prebid-cache.newsbreak.com",
// "hb_cache_id": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
// "hb_cache_id_msp_fb_a": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
// "hb_cache_path": "/cache",
// "hb_cache_path_msp_fb": "/cache",
// "hb_env": "mobile-app",
// "hb_env_msp_fb_alpha": "mobile-app",
// "hb_pb": "20.00",
// "hb_pb_msp_fb_alpha": "20.00"
// },
//
// Output:
//
// "targeting": {
// "hb_bidder": "audienceNetwork",
// "hb_bidder_audienceNe": "audienceNetwork",
// "hb_cache_host": "prebid-cache.newsbreak.com",
// "hb_cache_host_audien": "prebid-cache.newsbreak.com",
// "hb_cache_id": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
// "hb_cache_id_audience": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
// "hb_cache_path": "/cache",
// "hb_cache_path_audien": "/cache",
// "hb_env": "mobile-app",
// "hb_env_audienceNetwo": "mobile-app",
// "hb_pb": "20.00",
// "hb_pb_audienceNetwor": "20.00"
// },
func (m Module) HandleAuctionResponseHook(
_ context.Context,
miCtx hookstage.ModuleInvocationContext,
_ hookstage.ModuleInvocationContext,
payload hookstage.AuctionResponsePayload,
) (hookstage.HookResult[hookstage.AuctionResponsePayload], error) {
result := hookstage.HookResult[hookstage.AuctionResponsePayload]{}
resp := payload.BidResponse

for _, mapping := range m.Mappings {
err := modifyResponse(resp, mapping.Prefix, mapping.Bidder)
if err != nil {
return result, err
}
}

return result, nil
}

func modifyResponse(resp *openrtb2.BidResponse, prefix string, bidder string) error {
for i := range resp.SeatBid {
seatBid := &resp.SeatBid[i]

if strings.HasPrefix(seatBid.Seat, "msp_fb_") {
if strings.HasPrefix(seatBid.Seat, prefix) {
for j := range seatBid.Bid {
bid := &seatBid.Bid[j]

var ext openrtb_ext.ExtBid
err := json.Unmarshal(bid.Ext, &ext)
if err != nil {
glog.Errorf("Failed to unmarshal bid ext for bidder %s, error: %+v\n", seatBid.Seat, err)
return result, err
return err
}

ext.Prebid.Meta.AdapterCode = audienceNetwork
newTargeting := modifyTargeting(ext.Prebid.Targeting, seatBid.Seat)
ext.Prebid.Meta.AdapterCode = bidder
newTargeting := modifyTargeting(ext.Prebid.Targeting, seatBid.Seat, bidder)
ext.Prebid.Targeting = newTargeting

newExt, err := json.Marshal(ext)
if err != nil {
glog.Errorf("Failed to marshal bid ext for bidder %s, error: %+v\n", seatBid.Seat, err)
return result, err
return err
}

bid.Ext = newExt
}

seatBid.Seat = audienceNetwork
seatBid.Seat = bidder
}

}

return result, nil
return nil
}

// Example:
Expand Down Expand Up @@ -95,22 +138,22 @@ func (m Module) HandleAuctionResponseHook(
// "hb_pb_audienceNetwor": "20.00"
// },

func modifyTargeting(targeting map[string]string, bidder string) map[string]string {
func modifyTargeting(targeting map[string]string, multiCallBidder string, originBidder string) map[string]string {
new := make(map[string]string)

toBeModifiedKeys := make(map[string]string)
for _, prefix := range PREFIXES {
toBeModifiedKeys[assembleKey(prefix, bidder)] = assembleKey(prefix, audienceNetwork)
toBeModifiedKeys[assembleKey(prefix, multiCallBidder)] = assembleKey(prefix, originBidder)
}

for key, val := range targeting {
if key == "hb_bidder" {
new["hb_bidder"] = audienceNetwork
new["hb_bidder"] = originBidder
}

newVal := val
if newVal == bidder {
newVal = audienceNetwork
if newVal == multiCallBidder {
newVal = originBidder
}

if newKey, found := toBeModifiedKeys[key]; found {
Expand Down
82 changes: 82 additions & 0 deletions pkg/modules/multi_call/module/module_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package multi

import (
"reflect"
"testing"
)

func TestProcessingMspFB(t *testing.T) {
targeting := map[string]string{
"hb_bidder": "msp_fb_alpha",
"hb_bidder_msp_fb_alp": "msp_fb_alpha",
"hb_cache_host": "prebid-cache.newsbreak.com",
"hb_cache_host_msp_fb": "prebid-cache.newsbreak.com",
"hb_cache_id": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_id_msp_fb_a": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_path": "/cache",
"hb_cache_path_msp_fb": "/cache",
"hb_env": "mobile-app",
"hb_env_msp_fb_alpha": "mobile-app",
"hb_pb": "20.00",
"hb_pb_msp_fb_alpha": "20.00",
}
multiCallBidder := "msp_fb_alpha"
originBidder := "audienceNetwork"
actual := modifyTargeting(targeting, multiCallBidder, originBidder)

expected := map[string]string{
"hb_bidder": "audienceNetwork",
"hb_bidder_audienceNe": "audienceNetwork",
"hb_cache_host": "prebid-cache.newsbreak.com",
"hb_cache_host_audien": "prebid-cache.newsbreak.com",
"hb_cache_id": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_id_audience": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_path": "/cache",
"hb_cache_path_audien": "/cache",
"hb_env": "mobile-app",
"hb_env_audienceNetwo": "mobile-app",
"hb_pb": "20.00",
"hb_pb_audienceNetwor": "20.00",
}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Failed to get expected targeting\n, expected = %+#v\n, actual = %+#v\n", expected, actual)
}
}

func TestProcessingMspNova(t *testing.T) {
targeting := map[string]string{
"hb_bidder": "msp_nova_alpha",
"hb_bidder_msp_nova_a": "msp_nova_alpha",
"hb_cache_host": "prebid-cache.newsbreak.com",
"hb_cache_host_msp_no": "prebid-cache.newsbreak.com",
"hb_cache_id": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_id_msp_nova": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_path": "/cache",
"hb_cache_path_msp_no": "/cache",
"hb_env": "mobile-app",
"hb_env_msp_nova_alph": "mobile-app",
"hb_pb": "20.00",
"hb_pb_msp_nova_alpha": "20.00",
}
multiCallBidder := "msp_nova_alpha"
originBidder := "msp_nova"
actual := modifyTargeting(targeting, multiCallBidder, originBidder)

expected := map[string]string{
"hb_bidder": "msp_nova",
"hb_bidder_msp_nova": "msp_nova",
"hb_cache_host": "prebid-cache.newsbreak.com",
"hb_cache_host_msp_no": "prebid-cache.newsbreak.com",
"hb_cache_id": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_id_msp_nova": "a314c09e-3cf8-4c87-8fe4-2cc09cbbf09a",
"hb_cache_path": "/cache",
"hb_cache_path_msp_no": "/cache",
"hb_env": "mobile-app",
"hb_env_msp_nova": "mobile-app",
"hb_pb": "20.00",
"hb_pb_msp_nova": "20.00",
}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Failed to get expected targeting\n, expected = %+#v\n, actual = %+#v\n", expected, actual)
}
}
15 changes: 15 additions & 0 deletions static/bidder-info/msp_nova_alpha.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
endpoint: "https://business.newsbreak.com/api/ads"
disabled: true
maintainer:
email: "han.xiang@newsbreak.com"
capabilities:
app:
mediaTypes:
- banner
- video
- native
site:
mediaTypes:
- banner
- video
- native
15 changes: 15 additions & 0 deletions static/bidder-info/msp_nova_beta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
endpoint: "https://business.newsbreak.com/api/ads"
disabled: true
maintainer:
email: "han.xiang@newsbreak.com"
capabilities:
app:
mediaTypes:
- banner
- video
- native
site:
mediaTypes:
- banner
- video
- native
15 changes: 15 additions & 0 deletions static/bidder-info/msp_nova_gamma.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
endpoint: "https://business.newsbreak.com/api/ads"
disabled: true
maintainer:
email: "han.xiang@newsbreak.com"
capabilities:
app:
mediaTypes:
- banner
- video
- native
site:
mediaTypes:
- banner
- video
- native
13 changes: 13 additions & 0 deletions static/bidder-params/msp_nova_alpha.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Nova Adapter Params",
"description": "A schema which validates params accepted by the Nova adapter",
"type": "object",
"properties": {
"ad_unit": {
"type": "string",
"description": "Nova ad unit"
}
},
"required": ["ad_unit"]
}
13 changes: 13 additions & 0 deletions static/bidder-params/msp_nova_beta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Nova Adapter Params",
"description": "A schema which validates params accepted by the Nova adapter",
"type": "object",
"properties": {
"ad_unit": {
"type": "string",
"description": "Nova ad unit"
}
},
"required": ["ad_unit"]
}
13 changes: 13 additions & 0 deletions static/bidder-params/msp_nova_gamma.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Nova Adapter Params",
"description": "A schema which validates params accepted by the Nova adapter",
"type": "object",
"properties": {
"ad_unit": {
"type": "string",
"description": "Nova ad unit"
}
},
"required": ["ad_unit"]
}

0 comments on commit 7a72c37

Please sign in to comment.