From 46c7dab0802610f86f6f4210fa01e0d7cdd70e0e Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 27 Jun 2025 19:12:33 +0200 Subject: [PATCH 01/15] initial oprx adapter files --- adapters/oprx/oprx.go | 98 ++++++++++++++++++++++++++++++++++ openrtb_ext/imp_oprx.go | 11 ++++ static/bidder-info/oprx.yaml | 27 ++++++++++ static/bidder-params/oprx.json | 39 ++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 adapters/oprx/oprx.go create mode 100644 openrtb_ext/imp_oprx.go create mode 100644 static/bidder-info/oprx.yaml create mode 100644 static/bidder-params/oprx.json diff --git a/adapters/oprx/oprx.go b/adapters/oprx/oprx.go new file mode 100644 index 00000000000..5ab0b2f4843 --- /dev/null +++ b/adapters/oprx/oprx.go @@ -0,0 +1,98 @@ +package oprx + +import ( + "fmt" + "net/http" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +type adapter struct { + endpoint string +} + +// Builder builds a new instance of the {bidder} adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + requestJSON, err := jsonutil.Marshal(request) + if err != nil { + return nil, []error{err} + } + + requestData := &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: requestJSON, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + } + + return []*adapters.RequestData{requestData}, nil +} + +func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + if bid.Ext != nil { + var bidExt openrtb_ext.ExtBid + err := jsonutil.Unmarshal(bid.Ext, &bidExt) + if err == nil && bidExt.Prebid != nil { + return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) + } + } + + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), + } +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if responseData.StatusCode == http.StatusNoContent { + return nil, nil + } + + if responseData.StatusCode == http.StatusBadRequest { + err := &errortypes.BadInput{ + Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + } + return nil, []error{err} + } + + if responseData.StatusCode != http.StatusOK { + err := &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), + } + return nil, []error{err} + } + + var response openrtb2.BidResponse + if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil { + return nil, []error{err} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + bidResponse.Currency = response.Cur + var errors []error + for _, seatBid := range response.SeatBid { + for i, bid := range seatBid.Bid { + bidType, err := getMediaTypeForBid(bid) + if err != nil { + errors = append(errors, err) + continue + } + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + }) + } + } + return bidResponse, nil +} diff --git a/openrtb_ext/imp_oprx.go b/openrtb_ext/imp_oprx.go new file mode 100644 index 00000000000..804926227c1 --- /dev/null +++ b/openrtb_ext/imp_oprx.go @@ -0,0 +1,11 @@ +package openrtb_ext + +type ImpExtOprx struct { + Key string `json:"key"` + PlacementID string `json:"placement_id"` + Width string `json:"width"` + Height string `json:"height"` + BidFloor string `json:"bid_floor"` + Npi string `json:"npi"` + Ndc string `json:"ndc"` +} diff --git a/static/bidder-info/oprx.yaml b/static/bidder-info/oprx.yaml new file mode 100644 index 00000000000..c61273dd34a --- /dev/null +++ b/static/bidder-info/oprx.yaml @@ -0,0 +1,27 @@ +endpoint: "https://pb.optimizerx.com/pb" +endpointCompression: gzip +geoscope: + - USA + - CAN +maintainer: + email: adsupport@optimizerx.com +modifyingVastXmlAllowed: true +openrtb: + version: 2.6 +capabilities: + app: + mediaTypes: + - banner + - native + site: + mediaTypes: + - banner + - native + dooh: + mediaTypes: + - banner + - native +# userSync: +# redirect: +# url: https://foo.com/sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} +# userMacro: $UID \ No newline at end of file diff --git a/static/bidder-params/oprx.json b/static/bidder-params/oprx.json new file mode 100644 index 00000000000..6aa45fc6475 --- /dev/null +++ b/static/bidder-params/oprx.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "OptimizeRx Adapter Params", + "description": "A schema which validates params accepted by the OptimizeRx adapter", + "type": "object", + + "properties": { + "key": { + "type": "string", + "description": "Key" + }, + "placement_id": { + "type": "integer", + "description": "Placement ID" + }, + "width": { + "type": "integer", + "description": "Banner Width" + }, + "height": { + "type": "integer", + "description": "Banner Height" + }, + "bid_floor": { + "type": "number", + "description": "Bidding Price Floor" + }, + "npi": { + "type": "string", + "description": "NPI" + }, + "ndc": { + "type": "string", + "description": "NDC" + } + }, + + "required": ["key", "placement_id"] +} \ No newline at end of file From 1ff192ed6a72c048c0a1cfd7e614882216adc474 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 27 Jun 2025 19:28:37 +0200 Subject: [PATCH 02/15] registering oprx adapter --- exchange/adapter_builders.go | 2 ++ openrtb_ext/bidders.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 751934ac9bb..04247c67872 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -169,6 +169,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/openweb" "github.com/prebid/prebid-server/v3/adapters/openx" "github.com/prebid/prebid-server/v3/adapters/operaads" + "github.com/prebid/prebid-server/v3/adapters/oprx" "github.com/prebid/prebid-server/v3/adapters/optidigital" "github.com/prebid/prebid-server/v3/adapters/oraki" "github.com/prebid/prebid-server/v3/adapters/orbidder" @@ -427,6 +428,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderOpenWeb: openweb.Builder, openrtb_ext.BidderOpenx: openx.Builder, openrtb_ext.BidderOperaads: operaads.Builder, + openrtb_ext.BidderOprx: oprx.Builder, openrtb_ext.BidderOptidigital: optidigital.Builder, openrtb_ext.BidderOraki: oraki.Builder, openrtb_ext.BidderOrbidder: orbidder.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 102c9094c32..50152a6fd27 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -187,6 +187,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderOpenWeb, BidderOpenx, BidderOperaads, + BidderOprx, BidderOptidigital, BidderOraki, BidderOrbidder, @@ -549,6 +550,7 @@ const ( BidderOpenWeb BidderName = "openweb" BidderOpenx BidderName = "openx" BidderOperaads BidderName = "operaads" + BidderOprx BidderName = "oprx" BidderOptidigital BidderName = "optidigital" BidderOraki BidderName = "oraki" BidderOrbidder BidderName = "orbidder" From 835c115e38ef0fc30a6df3a7e2b61d5469fe4777 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 27 Jun 2025 20:00:46 +0200 Subject: [PATCH 03/15] started work on tests --- adapters/oprx/oprx_test.go | 21 +++++++++++++ .../oprx/oprxtest/exemplary/basic_flow.json | 30 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 adapters/oprx/oprx_test.go create mode 100644 adapters/oprx/oprxtest/exemplary/basic_flow.json diff --git a/adapters/oprx/oprx_test.go b/adapters/oprx/oprx_test.go new file mode 100644 index 00000000000..a6561da1c46 --- /dev/null +++ b/adapters/oprx/oprx_test.go @@ -0,0 +1,21 @@ +package oprx + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderOprx, config.Adapter{ + Endpoint: "http://any.url"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "oprxtest", bidder) +} diff --git a/adapters/oprx/oprxtest/exemplary/basic_flow.json b/adapters/oprx/oprxtest/exemplary/basic_flow.json new file mode 100644 index 00000000000..df58425dc52 --- /dev/null +++ b/adapters/oprx/oprxtest/exemplary/basic_flow.json @@ -0,0 +1,30 @@ +{ + "mockBidRequest": { + «OpenRTB 2.x Bid Request» + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "«Bidding Server Endpoint»", + "headers": { + "«Name»": ["«Value»"], + }, + "body": { + «Bidding Server Request Body» + } + }, + "mockResponse": { + "status": 200, + "headers": { + "«Name»": ["«Value»"], + }, + "body": { + «Bidding Server Response Body» + }, + }, + }], + "expectedBidResponses": [{ + "bids": [{ + «Prebid Server Bid Response» + }] + }] +} \ No newline at end of file From 8bec429edada03df2518ec606add3345eff6b44c Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Mon, 30 Jun 2025 10:28:35 +0200 Subject: [PATCH 04/15] fixed types in imp_oprx --- openrtb_ext/imp_oprx.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openrtb_ext/imp_oprx.go b/openrtb_ext/imp_oprx.go index 804926227c1..6775360c160 100644 --- a/openrtb_ext/imp_oprx.go +++ b/openrtb_ext/imp_oprx.go @@ -2,10 +2,10 @@ package openrtb_ext type ImpExtOprx struct { Key string `json:"key"` - PlacementID string `json:"placement_id"` - Width string `json:"width"` - Height string `json:"height"` - BidFloor string `json:"bid_floor"` + PlacementID int `json:"placement_id"` + Width int `json:"width"` + Height int `json:"height"` + BidFloor float64 `json:"bid_floor"` Npi string `json:"npi"` Ndc string `json:"ndc"` } From 96af0881f65123ce1cc64b6a6337469954f74454 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Mon, 30 Jun 2025 19:26:15 +0200 Subject: [PATCH 05/15] fixed params and banner test now works --- adapters/oprx/oprx_test.go | 22 ++-- adapters/oprx/oprxtest/exemplary/banner.json | 121 ++++++++++++++++++ .../oprx/oprxtest/exemplary/basic_flow.json | 30 ----- openrtb_ext/imp_oprx.go | 15 ++- static/bidder-info/oprx.yaml | 2 +- static/bidder-params/oprx.json | 6 +- 6 files changed, 146 insertions(+), 50 deletions(-) create mode 100644 adapters/oprx/oprxtest/exemplary/banner.json delete mode 100644 adapters/oprx/oprxtest/exemplary/basic_flow.json diff --git a/adapters/oprx/oprx_test.go b/adapters/oprx/oprx_test.go index a6561da1c46..392672215dc 100644 --- a/adapters/oprx/oprx_test.go +++ b/adapters/oprx/oprx_test.go @@ -1,21 +1,21 @@ package oprx import ( - "testing" + "testing" - "github.com/prebid/prebid-server/v3/adapters/adapterstest" - "github.com/prebid/prebid-server/v3/config" - "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" ) func TestJsonSamples(t *testing.T) { - bidder, buildErr := Builder(openrtb_ext.BidderOprx, config.Adapter{ - Endpoint: "http://any.url"}, - config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + bidder, buildErr := Builder(openrtb_ext.BidderOprx, config.Adapter{ + Endpoint: "http://localhost:8080"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) - if buildErr != nil { - t.Fatalf("Builder returned unexpected error %v", buildErr) - } + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } - adapterstest.RunJSONBidderTest(t, "oprxtest", bidder) + adapterstest.RunJSONBidderTest(t, "oprxtest", bidder) } diff --git a/adapters/oprx/oprxtest/exemplary/banner.json b/adapters/oprx/oprxtest/exemplary/banner.json new file mode 100644 index 00000000000..b24649e199a --- /dev/null +++ b/adapters/oprx/oprxtest/exemplary/banner.json @@ -0,0 +1,121 @@ +{ + "mockBidRequest": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://localhost:8080", + "body": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "bid-id", + "impid": "imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681110", + "h": 250, + "w": 300, + "dealid": "test deal", + "ext": { + "prebid": { + "type": "banner" + } + } + } + ] + } + ], + "bidid": "request-id", + "cur": "USD" + } + } + }], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-id", + "impid": "imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681110", + "h": 250, + "w": 300, + "dealid": "test deal", + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/oprx/oprxtest/exemplary/basic_flow.json b/adapters/oprx/oprxtest/exemplary/basic_flow.json deleted file mode 100644 index df58425dc52..00000000000 --- a/adapters/oprx/oprxtest/exemplary/basic_flow.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "mockBidRequest": { - «OpenRTB 2.x Bid Request» - }, - "httpCalls": [{ - "expectedRequest": { - "uri": "«Bidding Server Endpoint»", - "headers": { - "«Name»": ["«Value»"], - }, - "body": { - «Bidding Server Request Body» - } - }, - "mockResponse": { - "status": 200, - "headers": { - "«Name»": ["«Value»"], - }, - "body": { - «Bidding Server Response Body» - }, - }, - }], - "expectedBidResponses": [{ - "bids": [{ - «Prebid Server Bid Response» - }] - }] -} \ No newline at end of file diff --git a/openrtb_ext/imp_oprx.go b/openrtb_ext/imp_oprx.go index 6775360c160..96ce59c0b2e 100644 --- a/openrtb_ext/imp_oprx.go +++ b/openrtb_ext/imp_oprx.go @@ -1,11 +1,12 @@ package openrtb_ext type ImpExtOprx struct { - Key string `json:"key"` - PlacementID int `json:"placement_id"` - Width int `json:"width"` - Height int `json:"height"` - BidFloor float64 `json:"bid_floor"` - Npi string `json:"npi"` - Ndc string `json:"ndc"` + Key string `json:"key"` + PlacementID int `json:"placement_id"` + Width int `json:"width"` + Height int `json:"height"` + BidFloor float64 `json:"bid_floor"` + Npi string `json:"npi"` + Ndc string `json:"ndc"` + Type string `json:"type"` } diff --git a/static/bidder-info/oprx.yaml b/static/bidder-info/oprx.yaml index c61273dd34a..fce00fa4a3f 100644 --- a/static/bidder-info/oprx.yaml +++ b/static/bidder-info/oprx.yaml @@ -1,4 +1,4 @@ -endpoint: "https://pb.optimizerx.com/pb" +endpoint: "http://localhost:8080" endpointCompression: gzip geoscope: - USA diff --git a/static/bidder-params/oprx.json b/static/bidder-params/oprx.json index 6aa45fc6475..1b59efc5f38 100644 --- a/static/bidder-params/oprx.json +++ b/static/bidder-params/oprx.json @@ -32,8 +32,12 @@ "ndc": { "type": "string", "description": "NDC" + }, + "type": { + "type": "string", + "description": "Type of Bid/Impression" } }, - "required": ["key", "placement_id"] + "required": ["key", "placement_id", "type"] } \ No newline at end of file From bd13367e0eb4b8c6d748475beb04312dd71e3f04 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 11 Jul 2025 11:57:57 +0200 Subject: [PATCH 06/15] added params tests --- adapters/oprx/params_test.go | 65 ++++++++++++++++++++++++++++++++++++ static/bidder-info/oprx.yaml | 9 +---- 2 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 adapters/oprx/params_test.go diff --git a/adapters/oprx/params_test.go b/adapters/oprx/params_test.go new file mode 100644 index 00000000000..ec49bd4c732 --- /dev/null +++ b/adapters/oprx/params_test.go @@ -0,0 +1,65 @@ +package oprx + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json schema. %v", err) + } + + for _, p := range validParams { + if err := validator.Validate(openrtb_ext.BidderOprx, json.RawMessage(p)); err != nil { + t.Errorf("Schema rejected valid params: %s", p) + } + } +} + +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json schema. %v", err) + } + + for _, p := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderOprx, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + } +} + +var validParams = []string{ + `{"key": "some key", "placement_id": 1234567890, "type": "banner"}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "width": 1234}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "height": 5678}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "bid_floor": 1.23}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "npi": "some npi"}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "ndc": "some ndc"}`, +} + +var invalidParams = []string{ + `{"key": 1234567, "placement_id": 1234567890, "type": "banner"}`, + `{"placement_id": "1234567890", "key": "some key", "type": "banner"}`, + `{"key": "some key", "placement_id": 1234567890, "type": 12}`, + `{"key": "some key"}`, + `{"placement_id": 1234567890, "type": 12}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "width": "1234"}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "height": "5678"}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "bid_floor": "1.23"}`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "npi": 1223456`, + `{"key": "some key", "placement_id": 1234567890, "type": "banner", "ndc": 876543}`, +} + +// Key string `json:"key"` +// PlacementID int `json:"placement_id"` +// Width int `json:"width"` +// Height int `json:"height"` +// BidFloor float64 `json:"bid_floor"` +// Npi string `json:"npi"` +// Ndc string `json:"ndc"` +// Type string `json:"type"` diff --git a/static/bidder-info/oprx.yaml b/static/bidder-info/oprx.yaml index fce00fa4a3f..30034fd4216 100644 --- a/static/bidder-info/oprx.yaml +++ b/static/bidder-info/oprx.yaml @@ -12,16 +12,9 @@ capabilities: app: mediaTypes: - banner - - native site: mediaTypes: - banner - - native dooh: mediaTypes: - - banner - - native -# userSync: -# redirect: -# url: https://foo.com/sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} -# userMacro: $UID \ No newline at end of file + - banner \ No newline at end of file From bc443bfdd3648e096e8b90771ef3bf21f7d80833 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 11 Jul 2025 12:39:54 +0200 Subject: [PATCH 07/15] endpoint changed from testing one (localhost) --- static/bidder-info/oprx.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/bidder-info/oprx.yaml b/static/bidder-info/oprx.yaml index 30034fd4216..346fca8b5c1 100644 --- a/static/bidder-info/oprx.yaml +++ b/static/bidder-info/oprx.yaml @@ -1,4 +1,4 @@ -endpoint: "http://localhost:8080" +endpoint: "https://pb.optimizerx.com/pb" endpointCompression: gzip geoscope: - USA From 6ca184391e6a50d26b2ce3fc3eacb6402d9d4e36 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 11 Jul 2025 12:45:14 +0200 Subject: [PATCH 08/15] cleanup --- adapters/oprx/params_test.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/adapters/oprx/params_test.go b/adapters/oprx/params_test.go index ec49bd4c732..b5afdf864c4 100644 --- a/adapters/oprx/params_test.go +++ b/adapters/oprx/params_test.go @@ -54,12 +54,3 @@ var invalidParams = []string{ `{"key": "some key", "placement_id": 1234567890, "type": "banner", "npi": 1223456`, `{"key": "some key", "placement_id": 1234567890, "type": "banner", "ndc": 876543}`, } - -// Key string `json:"key"` -// PlacementID int `json:"placement_id"` -// Width int `json:"width"` -// Height int `json:"height"` -// BidFloor float64 `json:"bid_floor"` -// Npi string `json:"npi"` -// Ndc string `json:"ndc"` -// Type string `json:"type"` From 832fbbee6b383a61df5e53029772f2629d584782 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 25 Jul 2025 16:05:51 +0200 Subject: [PATCH 09/15] removed comments --- adapters/oprx/oprx.go | 1 - 1 file changed, 1 deletion(-) diff --git a/adapters/oprx/oprx.go b/adapters/oprx/oprx.go index 5ab0b2f4843..0ed2f527061 100644 --- a/adapters/oprx/oprx.go +++ b/adapters/oprx/oprx.go @@ -16,7 +16,6 @@ type adapter struct { endpoint string } -// Builder builds a new instance of the {bidder} adapter for the given bidder with the given config. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { bidder := &adapter{ endpoint: config.Endpoint, From 5870c1f1a861c9cb31f2363efce5e613b1a8610e Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 25 Jul 2025 16:22:19 +0200 Subject: [PATCH 10/15] moved getMediaTypeForBid to the end of file --- adapters/oprx/oprx.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/adapters/oprx/oprx.go b/adapters/oprx/oprx.go index 0ed2f527061..20168d367c6 100644 --- a/adapters/oprx/oprx.go +++ b/adapters/oprx/oprx.go @@ -39,20 +39,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte return []*adapters.RequestData{requestData}, nil } -func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { - if bid.Ext != nil { - var bidExt openrtb_ext.ExtBid - err := jsonutil.Unmarshal(bid.Ext, &bidExt) - if err == nil && bidExt.Prebid != nil { - return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) - } - } - - return "", &errortypes.BadServerResponse{ - Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), - } -} - func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { if responseData.StatusCode == http.StatusNoContent { return nil, nil @@ -95,3 +81,17 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } return bidResponse, nil } + +func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + if bid.Ext != nil { + var bidExt openrtb_ext.ExtBid + err := jsonutil.Unmarshal(bid.Ext, &bidExt) + if err == nil && bidExt.Prebid != nil { + return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) + } + } + + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), + } +} From b85506132293d464adaf34bf1b6e0ac649753c31 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 25 Jul 2025 18:43:31 +0200 Subject: [PATCH 11/15] added some new test cases --- .../oprx/oprxtest/exemplary/multi-imp.json | 202 ++++++++++++++++++ .../oprxtest/supplemental/bad-media-type.json | 95 ++++++++ .../oprxtest/supplemental/bad-request.json | 68 ++++++ .../oprx/oprxtest/supplemental/no-bid.json | 62 ++++++ 4 files changed, 427 insertions(+) create mode 100644 adapters/oprx/oprxtest/exemplary/multi-imp.json create mode 100644 adapters/oprx/oprxtest/supplemental/bad-media-type.json create mode 100644 adapters/oprx/oprxtest/supplemental/bad-request.json create mode 100644 adapters/oprx/oprxtest/supplemental/no-bid.json diff --git a/adapters/oprx/oprxtest/exemplary/multi-imp.json b/adapters/oprx/oprxtest/exemplary/multi-imp.json new file mode 100644 index 00000000000..9cb6bd4d9ec --- /dev/null +++ b/adapters/oprx/oprxtest/exemplary/multi-imp.json @@ -0,0 +1,202 @@ +{ + "mockBidRequest": { + "id": "request-id", + "imp": [ + { + "id": "imp-id-1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id-1", + "bid-floor": 0.5, + "npi": "my-npi-1", + "ndc": "my-ndc-1" + } + } + }, + { + "id": "imp-id-2", + "banner": { + "format": [ + { + "w": 350, + "h": 200 + } + ] + }, + "ext": { + "bidder": { + "key": "p567", + "placement_id": "my-placement-id-2", + "bid-floor": 0.5, + "npi": "my-npi-2", + "ndc": "my-ndc-2" + } + } + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://localhost:8080", + "body": { + "id": "request-id", + "imp": [ + { + "id": "imp-id-1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id-1", + "bid-floor": 0.5, + "npi": "my-npi-1", + "ndc": "my-ndc-1" + } + } + }, + { + "id": "imp-id-2", + "banner": { + "format": [ + { + "w": 350, + "h": 200 + } + ] + }, + "ext": { + "bidder": { + "key": "p567", + "placement_id": "my-placement-id-2", + "bid-floor": 0.5, + "npi": "my-npi-2", + "ndc": "my-ndc-2" + } + } + } + ] + }, + "impIDs": ["imp-id-1", "imp-id-2"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "bid-id-1", + "impid": "imp-id-1", + "price": 0.5, + "adid": "29681111", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681111", + "h": 250, + "w": 300, + "dealid": "test deal 1", + "ext": { + "prebid": { + "type": "banner" + } + } + }, + { + "id": "bid-id-2", + "impid": "imp-id-2", + "price": 0.5, + "adid": "29681112", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681112", + "h": 200, + "w": 350, + "dealid": "test deal 2", + "ext": { + "prebid": { + "type": "banner" + } + } + } + ] + } + ], + "bidid": "request-id", + "cur": "USD" + } + } + }], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-id-1", + "impid": "imp-id-1", + "price": 0.5, + "adid": "29681111", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681111", + "h": 250, + "w": 300, + "dealid": "test deal 1", + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-id-2", + "impid": "imp-id-2", + "price": 0.5, + "adid": "29681112", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681112", + "h": 200, + "w": 350, + "dealid": "test deal 2", + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/oprx/oprxtest/supplemental/bad-media-type.json b/adapters/oprx/oprxtest/supplemental/bad-media-type.json new file mode 100644 index 00000000000..d523aa72fb7 --- /dev/null +++ b/adapters/oprx/oprxtest/supplemental/bad-media-type.json @@ -0,0 +1,95 @@ +{ + "mockBidRequest": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://localhost:8080", + "body": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "impIDs": ["imp-id"] + },"mockResponse": { + "status": 200, + "body": { + "id": "request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "bid-id", + "impid": "imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "foo.com" + ], + "crid": "29681110", + "h": 250, + "w": 300, + "dealid": "test deal", + "ext": { + "prebid": { + "type": "bamer" + } + } + } + ] + } + ], + "bidid": "request-id", + "cur": "USD" + } + } + }], + "expectedBidResponses": [{ + "currency": "USD", + "bids": [] +}] +} \ No newline at end of file diff --git a/adapters/oprx/oprxtest/supplemental/bad-request.json b/adapters/oprx/oprxtest/supplemental/bad-request.json new file mode 100644 index 00000000000..40fee76eaf4 --- /dev/null +++ b/adapters/oprx/oprxtest/supplemental/bad-request.json @@ -0,0 +1,68 @@ +{ + "mockBidRequest": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://localhost:8080", + "body": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 400 + } + }], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/oprx/oprxtest/supplemental/no-bid.json b/adapters/oprx/oprxtest/supplemental/no-bid.json new file mode 100644 index 00000000000..1e049f63f72 --- /dev/null +++ b/adapters/oprx/oprxtest/supplemental/no-bid.json @@ -0,0 +1,62 @@ +{ + "mockBidRequest": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://localhost:8080", + "body": { + "id": "request-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "key": "p123", + "placement_id": "my-placement-id", + "bid-floor": 0.5, + "npi": "my-npi", + "ndc": "my-ndc" + } + } + } + ] + }, + "impIDs": ["imp-id"] + }, + "mockResponse": { + "status": 204 + } + }], + "expectedBidResponses": [] +} \ No newline at end of file From b639119c07fcdb0c43cc22c0f0720ec4c2e64fb6 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Mon, 28 Jul 2025 11:33:54 +0200 Subject: [PATCH 12/15] fixed formatting --- openrtb_ext/bidders.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 50152a6fd27..47004b3abb8 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -550,7 +550,7 @@ const ( BidderOpenWeb BidderName = "openweb" BidderOpenx BidderName = "openx" BidderOperaads BidderName = "operaads" - BidderOprx BidderName = "oprx" + BidderOprx BidderName = "oprx" BidderOptidigital BidderName = "optidigital" BidderOraki BidderName = "oraki" BidderOrbidder BidderName = "orbidder" From 6c94fb946944822632216f2c87e4b82dfafd01ae Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 27 Feb 2026 17:17:13 +0100 Subject: [PATCH 13/15] comments addressed --- adapters/oprx/oprx.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/adapters/oprx/oprx.go b/adapters/oprx/oprx.go index 20168d367c6..cfcf657b6fd 100644 --- a/adapters/oprx/oprx.go +++ b/adapters/oprx/oprx.go @@ -40,14 +40,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { - if responseData.StatusCode == http.StatusNoContent { + if adapters.IsResponseStatusCodeNoContent(responseData) { return nil, nil } - if responseData.StatusCode == http.StatusBadRequest { - err := &errortypes.BadInput{ - Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", - } + if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { return nil, []error{err} } From 96321f800820d3aadb70dd0964bbdc29df54dfd6 Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 27 Feb 2026 17:23:18 +0100 Subject: [PATCH 14/15] tests aligned --- adapters/oprx/oprxtest/supplemental/bad-request.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/oprx/oprxtest/supplemental/bad-request.json b/adapters/oprx/oprxtest/supplemental/bad-request.json index 40fee76eaf4..a9d9f053c58 100644 --- a/adapters/oprx/oprxtest/supplemental/bad-request.json +++ b/adapters/oprx/oprxtest/supplemental/bad-request.json @@ -61,7 +61,7 @@ "expectedBidResponses": [], "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info.", "comparison": "literal" } ] From f3d84e943b07e1abf7e7732d7080fd42a751334b Mon Sep 17 00:00:00 2001 From: Ivan Zivkovic Date: Fri, 27 Feb 2026 17:29:29 +0100 Subject: [PATCH 15/15] typo --- adapters/oprx/oprxtest/supplemental/bad-request.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/oprx/oprxtest/supplemental/bad-request.json b/adapters/oprx/oprxtest/supplemental/bad-request.json index a9d9f053c58..18100fa3afc 100644 --- a/adapters/oprx/oprxtest/supplemental/bad-request.json +++ b/adapters/oprx/oprxtest/supplemental/bad-request.json @@ -61,7 +61,7 @@ "expectedBidResponses": [], "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 400. Run with request.debug = 1 for more info.", + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", "comparison": "literal" } ]