Skip to content
51 changes: 36 additions & 15 deletions adapters/missena/missena.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type MissenaAdRequest struct {
Adunit string `json:"adunit,omitempty"`
BuyerUID string `json:"buyeruid,omitempty"`
Currency string `json:"currency,omitempty"`
Debug bool `json:"debug,omitempty"`
EIDs []openrtb2.EID `json:"userEids,omitempty"`
Floor float64 `json:"floor,omitempty"`
FloorCurrency string `json:"floor_currency,omitempty"`
Expand All @@ -43,19 +44,19 @@ type BidServerResponse struct {
}
Comment thread
postindustria-code marked this conversation as resolved.

type UserParams struct {
APIKey string `json:"apiKey,omitempty"`
Formats []string `json:"formats,omitempty"`
Placement string `json:"placement,omitempty" default:"sticky"`
TestMode string `json:"test,omitempty"`
Sample string `json:"sample,omitempty"`
Settings map[string]any `json:"settings,omitempty"`
}

Comment thread
postindustria-code marked this conversation as resolved.
type MissenaAdapter struct {
EndpointTemplate *template.Template
}

var defaultCur = "USD"
const (
currencyUSD = "USD"
currencyEUR = "EUR"
)

// Builder builds a new instance of the Foo adapter for the given bidder with the given config.
// Builder builds a new instance of the Missena adapter for the given bidder with the given config.
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
endpoint, err := template.New("endpointTemplate").Parse(config.Endpoint)
if err != nil {
Expand All @@ -67,18 +68,25 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co
return bidder, nil
}

func getVersionString() string {
if version.Ver == "" {
return version.VerUnknown
}
return version.Ver
}

func getCurrency(currencies []string) (string, error) {
eurAvailable := false
for _, cur := range currencies {
if cur == defaultCur {
return defaultCur, nil
if cur == currencyUSD {
return currencyUSD, nil
}
if cur == "EUR" {
if cur == currencyEUR {
eurAvailable = true
}
}
if eurAvailable {
return "EUR", nil
return currencyEUR, nil
}
return "", fmt.Errorf("no currency supported %v", currencies)
}
Expand All @@ -97,7 +105,7 @@ func (a *adapter) makeRequest(imp openrtb2.Imp, request *openrtb2.BidRequest, re
}
cur, err := getCurrency(request.Cur)
if err != nil {
cur = defaultCur
cur = currencyUSD
}

var floor float64
Expand All @@ -106,30 +114,43 @@ func (a *adapter) makeRequest(imp openrtb2.Imp, request *openrtb2.BidRequest, re
floor = imp.BidFloor
floorCur, err = getCurrency(request.Cur)
if err != nil {
floorCur = defaultCur
floorCur = currencyUSD
floor, err = requestInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, floorCur)
if err != nil {
return nil, err
}
}
}

// Extract EIDs from user.ext. Unmarshal errors are intentionally ignored
// to allow requests to proceed without EIDs, as they are optional.
var eids []openrtb2.EID
if request.User != nil && request.User.Ext != nil {
var extUser openrtb_ext.ExtUser
if err := jsonutil.Unmarshal(request.User.Ext, &extUser); err == nil {
eids = extUser.Eids
}
}
Comment on lines +127 to +133

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Could you please add/update the JSON test cases to cover this new field as well?
  2. You are silently ignoring the unmarshal error here, is it intentional? Is the idea that invalid user.ext should simply result in missing EIDs rather than a hard error?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

  1. Added a new JSON test case: simple-banner-with-eids.json that covers the EIDs field with multiple sources

  2. Yes, the silent error handling is intentional. I've added a comment to clarify this. The rationale is:

  • EIDs are optional data for targeting/identification
  • If user.ext is malformed, we want the bid request to proceed without EIDs rather than fail entirely
  • This follows the same defensive pattern used elsewhere in the adapter (e.g., readGDPR function)


missenaRequest := MissenaAdRequest{
Adunit: imp.ID,
Currency: cur,
Debug: request.Test == 1,
Floor: floor,
FloorCurrency: floorCur,
IdempotencyKey: request.ID,
ORTB2: request,
RequestID: request.ID,
Comment thread
postindustria-code marked this conversation as resolved.
Timeout: request.TMax,
UserParams: UserParams{
APIKey: params.APIKey,
Formats: params.Formats,
Placement: params.Placement,
TestMode: params.TestMode,
Sample: params.Sample,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you include JSON test coverage cases for this field?

Settings: params.Settings,
},
Version: version.Ver,
EIDs: eids,
Version: fmt.Sprintf("prebid-server@%s", getVersionString()),
}

body, err := jsonutil.Marshal(missenaRequest)
Comment thread
postindustria-code marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@
"request_id": "test-request-id",
"timeout": 500,
"params": {
"apiKey": "test-api-key",
"formats": ["banner"],
"placement": "sticky"
}
},
"version": "prebid-server@unknown"
},
"impIDs": ["test-imp-id"]
},
Expand Down
7 changes: 4 additions & 3 deletions adapters/missena/missenatest/exemplary/multiple-imps.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,12 @@
}
},
"params": {
"placement": "test-placement-1",
"test": "1"
"apiKey": "test-api-key",
"placement": "test-placement-1"
},
"request_id": "test-request-id",
"timeout": 500
"timeout": 500,
"version": "prebid-server@unknown"
},
"impIDs": ["test-imp-id-1"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,12 @@
}
},
"params": {
"placement": "test-placement",
"test": "1"
"apiKey": "test-api-key",
"placement": "test-placement"
},
"request_id": "test-request-id",
"timeout": 500
"timeout": 500,
"version": "prebid-server@unknown"
},
"impIDs": ["test-imp-id"]
},
Expand Down
194 changes: 194 additions & 0 deletions adapters/missena/missenatest/exemplary/simple-banner-with-eids.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
{
"mockBidRequest": {
"id": "test-request-id",
"tmax": 500,
"at": 1,
"cur": ["EUR"],
"regs": {
"ext": {
"gdpr": 1
}
},
"user": {
"ext": {
"consent": "CO-X2XiO_eyUoAsAxBFRBECsA",
"eids": [
{
"source": "adserver.org",
"uids": [
{
"id": "111111111111",
"atype": 1
}
]
},
{
"source": "liveramp.com",
"uids": [
{
"id": "AjfowMv4ZHZQME1RWTn",
"atype": 3
}
]
}
]
}
},
"device": {
"ip": "123.123.123.123",
"ua": "test-user-agent"
},
"site": {
"page": "https://example.com/page",
"domain": "example.com"
},
"imp": [
{
"id": "test-imp-id",
"banner": {
"h": 50,
"w": 320
},
"ext": {
"bidder": {
"apiKey": "test-api-key",
"placement": "test-placement"
}
}
}
]
},
"httpCalls": [
{
"expectedRequest": {
"uri": "http://example.com/?t=test-api-key",
"headers": {
"Content-Type": ["application/json;charset=utf-8"],
"Accept": ["application/json"],
"User-Agent": ["test-user-agent"],
"X-Forwarded-For": ["123.123.123.123"],
"Referer": ["https://example.com/page"],
"Origin": ["https://example.com"]
},
"body": {
"adunit": "test-imp-id",
"currency": "EUR",
"ik": "test-request-id",
"ortb2": {
"at": 1,
"cur": ["EUR"],
"device": {
"ip": "123.123.123.123",
"ua": "test-user-agent"
},
"id": "test-request-id",
"imp": [
{
"banner": {
"h": 50,
"w": 320
},
"ext": {
"bidder": {
"apiKey": "test-api-key",
"placement": "test-placement"
}
},
"id": "test-imp-id"
}
],
"regs": {
"ext": {
"gdpr": 1
}
},
"site": {
"domain": "example.com",
"page": "https://example.com/page"
},
"tmax": 500,
"user": {
"ext": {
"consent": "CO-X2XiO_eyUoAsAxBFRBECsA",
"eids": [
{
"source": "adserver.org",
"uids": [
{
"id": "111111111111",
"atype": 1
}
]
},
{
"source": "liveramp.com",
"uids": [
{
"id": "AjfowMv4ZHZQME1RWTn",
"atype": 3
}
]
}
]
}
}
},
"params": {
"apiKey": "test-api-key",
"placement": "test-placement"
},
"request_id": "test-request-id",
"timeout": 500,
"userEids": [
{
"source": "adserver.org",
"uids": [
{
"id": "111111111111",
"atype": 1
}
]
},
{
"source": "liveramp.com",
"uids": [
{
"id": "AjfowMv4ZHZQME1RWTn",
"atype": 3
}
]
}
],
"version": "prebid-server@unknown"
},
"impIDs": ["test-imp-id"]
},
"mockResponse": {
"status": 200,
"body": {
"ad": "<div>test ad</div>",
"cpm": 1.5,
"currency": "EUR",
"requestId": "test-request-id"
}
}
}
],
"expectedBidResponses": [
{
"currency": "EUR",
"bids": [
{
"bid": {
"id": "test-request-id",
"impid": "test-imp-id",
"price": 1.5,
"adm": "<div>test ad</div>",
"crid": "test-request-id"
},
"type": "banner"
}
]
}
]
}
Loading
Loading