From 484d41e8f88b7557b32e588d34151ae6f7594f1a Mon Sep 17 00:00:00 2001 From: Volokha Date: Tue, 10 Feb 2026 15:07:33 +0200 Subject: [PATCH 1/6] add rtbstack adapter for pbs --- adapters/rtbstack/rtbstack.go | 190 ++++++++++++++++++ adapters/rtbstack/rtbstack_test.go | 19 ++ .../rtbstacktest/exemplary/app-audio.json | 148 ++++++++++++++ .../rtbstacktest/exemplary/app-banner.json | 128 ++++++++++++ .../rtbstacktest/exemplary/app-native.json | 140 +++++++++++++ .../rtbstacktest/exemplary/app-video.json | 156 ++++++++++++++ .../exemplary/optional-params.json | 177 ++++++++++++++++ .../rtbstacktest/exemplary/site-audio.json | 140 +++++++++++++ .../rtbstacktest/exemplary/site-banner.json | 181 +++++++++++++++++ .../exemplary/site-domain-empty-mutation.json | 59 ++++++ .../exemplary/site-domain-mutation.json | 60 ++++++ .../rtbstacktest/exemplary/site-native.json | 142 +++++++++++++ .../rtbstacktest/exemplary/site-video.json | 152 ++++++++++++++ .../rtbstacktest/supplemental/bad-imp.json | 29 +++ .../supplemental/bad-response.json | 70 +++++++ .../rtbstacktest/supplemental/status-204.json | 58 ++++++ .../rtbstacktest/supplemental/status-400.json | 64 ++++++ .../supplemental/two-imps-one-is-bad.json | 69 +++++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_rtbstack.go | 7 + static/bidder-info/rtbstack.yaml | 16 ++ static/bidder-params/rtbstack.json | 23 +++ 23 files changed, 2032 insertions(+) create mode 100644 adapters/rtbstack/rtbstack.go create mode 100644 adapters/rtbstack/rtbstack_test.go create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/app-audio.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/app-banner.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/app-native.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/app-video.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/optional-params.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/site-audio.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/site-banner.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/site-native.json create mode 100644 adapters/rtbstack/rtbstacktest/exemplary/site-video.json create mode 100644 adapters/rtbstack/rtbstacktest/supplemental/bad-imp.json create mode 100644 adapters/rtbstack/rtbstacktest/supplemental/bad-response.json create mode 100644 adapters/rtbstack/rtbstacktest/supplemental/status-204.json create mode 100644 adapters/rtbstack/rtbstacktest/supplemental/status-400.json create mode 100644 adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json create mode 100644 openrtb_ext/imp_rtbstack.go create mode 100644 static/bidder-info/rtbstack.yaml create mode 100644 static/bidder-params/rtbstack.json diff --git a/adapters/rtbstack/rtbstack.go b/adapters/rtbstack/rtbstack.go new file mode 100644 index 00000000000..5c5c5e6fdce --- /dev/null +++ b/adapters/rtbstack/rtbstack.go @@ -0,0 +1,190 @@ +package rtbstack + +import ( + "encoding/json" + "fmt" + "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" + "net/http" + "strings" +) + +const endpointMacro = "http://{{.Host}}" + +type adapter struct { + endpoint string +} + +// impCtx represents the context containing an OpenRTB impression and its corresponding RTBStack extension configuration. +type impCtx struct { + imp openrtb2.Imp + rtbStackExt *openrtb_ext.ExtImpRTBStack +} + +// extImpRTBStack is used for imp->ext when sending to rtb-stack backend +type extImpRTBStack struct { + TagId string `json:"tagid"` + CustomParams map[string]interface{} `json:"customParams,omitempty"` +} + +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, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + if len(request.Imp) == 0 { + return nil, []error{&errortypes.BadInput{ + Message: "No impressions in request", + }} + } + + var errs []error + var validImps []*impCtx + + for i := range request.Imp { + imp := request.Imp[i] + + ext, err := preprocessImp(&imp) + if err != nil { + errs = append(errs, err) + continue + } + + validImps = append(validImps, &impCtx{ + imp: imp, + rtbStackExt: ext, + }) + } + + if len(validImps) == 0 { + return nil, errs + } + + request.Imp = nil + for _, v := range validImps { + request.Imp = append(request.Imp, v.imp) + } + + endpoint := a.buildEndpointURL(validImps[0].rtbStackExt) + + var newRequest openrtb2.BidRequest + newRequest = *request + + if request.Site != nil && request.Site.Domain == "" { + newSite := *request.Site + newSite.Domain = request.Site.Page + newRequest.Site = &newSite + } + + reqJSON, err := json.Marshal(newRequest) + if err != nil { + return nil, []error{&errortypes.BadInput{ + Message: "Error parsing reqJSON object", + }} + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + return []*adapters.RequestData{{ + Method: "POST", + Uri: endpoint, + Body: reqJSON, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + }}, []error{} +} + +func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if response.StatusCode == http.StatusNoContent { + return nil, nil + } + + if response.StatusCode != http.StatusOK { + return nil, []error{fmt.Errorf("Unexpected status code: %d", response.StatusCode)} + } + + var bidResp openrtb2.BidResponse + if err := jsonutil.Unmarshal(response.Body, &bidResp); err != nil { + return nil, []error{err} + } + + if len(bidResp.SeatBid) == 0 || len(bidResp.SeatBid[0].Bid) == 0 { + return nil, nil + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) + + for _, sb := range bidResp.SeatBid { + for i := 0; i < len(sb.Bid); i++ { + bid := sb.Bid[i] + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp), + }) + + } + } + return bidResponse, []error{} +} + +func (a *adapter) buildEndpointURL(ext *openrtb_ext.ExtImpRTBStack) string { + return strings.Replace(a.endpoint, endpointMacro, ext.Endpoint, -1) +} + +func preprocessImp( + imp *openrtb2.Imp, +) (*openrtb_ext.ExtImpRTBStack, error) { + var bidderExt adapters.ExtImpBidder + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { + return nil, &errortypes.BadInput{Message: err.Error()} + } + + var impExt openrtb_ext.ExtImpRTBStack + if err := jsonutil.Unmarshal(bidderExt.Bidder, &impExt); err != nil { + return nil, &errortypes.BadInput{ + Message: "Wrong RTBStack bidder ext", + } + } + + imp.TagID = impExt.TagId + + // create new imp->ext without odd params + newExt := extImpRTBStack{ + TagId: impExt.TagId, + CustomParams: impExt.CustomParams, + } + + // simplify content from imp->ext->bidder to imp->ext + newImpExtForRTBStack, err := json.Marshal(newExt) + if err != nil { + return nil, &errortypes.BadInput{Message: err.Error()} + } + imp.Ext = newImpExtForRTBStack + + return &impExt, nil +} + +func getMediaTypeForImp(impID string, imps []openrtb2.Imp) openrtb_ext.BidType { + for _, imp := range imps { + if imp.ID == impID { + if imp.Banner != nil { + return openrtb_ext.BidTypeBanner + } else if imp.Video != nil { + return openrtb_ext.BidTypeVideo + } else if imp.Native != nil { + return openrtb_ext.BidTypeNative + } else if imp.Audio != nil { + return openrtb_ext.BidTypeAudio + } + } + } + return openrtb_ext.BidTypeBanner +} diff --git a/adapters/rtbstack/rtbstack_test.go b/adapters/rtbstack/rtbstack_test.go new file mode 100644 index 00000000000..a55841f5183 --- /dev/null +++ b/adapters/rtbstack/rtbstack_test.go @@ -0,0 +1,19 @@ +package rtbstack + +import ( + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "testing" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderRTBStack, config.Adapter{ + Endpoint: "http://{{.Host}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "rtbstacktest", bidder) +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json b/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json new file mode 100644 index 00000000000..939c54f2526 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json @@ -0,0 +1,148 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-audio-short", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 5, + "maxduration": 30 + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-audio-short", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-app-audio-long", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 15, + "maxduration": 60 + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-audio-long", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-audio-short", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 5, + "maxduration": 30 + }, + "tagid": "app-audio-short", + "ext": { + "tagid": "app-audio-short", + "customParams": { + "foo": "bar" + } + } + }, + { + "id": "imp-app-audio-long", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 15, + "maxduration": 60 + }, + "tagid": "app-audio-long", + "ext": { + "tagid": "app-audio-long" + } + } + ] + }, + "impIDs": ["imp-app-audio-short", "imp-app-audio-long"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-app-audio-short-1", + "impid": "imp-app-audio-short", + "price": 0.75, + "adm": "", + "crid": "crid-app-audio-short-1" + }, + { + "id": "bid-app-audio-long-1", + "impid": "imp-app-audio-long", + "price": 1.25, + "adm": "", + "crid": "crid-app-audio-long-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-app-audio-short-1", + "impid": "imp-app-audio-short", + "price": 0.75, + "adm": "", + "crid": "crid-app-audio-short-1" + }, + "type": "audio" + }, + { + "bid": { + "id": "bid-app-audio-long-1", + "impid": "imp-app-audio-long", + "price": 1.25, + "adm": "", + "crid": "crid-app-audio-long-1" + }, + "type": "audio" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json b/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json new file mode 100644 index 00000000000..50c095395cb --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json @@ -0,0 +1,128 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-basic", + "banner": { + "format": [{ "w": 320, "h": 50 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-basic", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-app-large", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-large", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "app": { "bundle": "com.prebid.app" }, + "device": { "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" }, + "imp": [ + { + "id": "imp-app-basic", + "banner": { "format": [{ "w": 320, "h": 50 }] }, + "tagid": "app-basic", + "ext": { + "tagid": "app-basic", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-app-large", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "app-large", + "ext": { "tagid": "app-large" } + } + ] + }, + "impIDs": ["imp-app-basic", "imp-app-large"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-app-basic-1", + "impid": "imp-app-basic", + "price": 0.95, + "adm": "
App Banner 320x50
", + "crid": "crid-app-basic-1" + }, + { + "id": "bid-app-large-1", + "impid": "imp-app-large", + "price": 1.50, + "adm": "
App Banner 728x90
", + "crid": "crid-app-large-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-app-basic-1", + "impid": "imp-app-basic", + "price": 0.95, + "adm": "
App Banner 320x50
", + "crid": "crid-app-basic-1" + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-app-large-1", + "impid": "imp-app-large", + "price": 1.50, + "adm": "
App Banner 728x90
", + "crid": "crid-app-large-1" + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-native.json b/adapters/rtbstack/rtbstacktest/exemplary/app-native.json new file mode 100644 index 00000000000..7a7f3974721 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-native.json @@ -0,0 +1,140 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-native-small", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":120,\"hmin\":120,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":100}}]}" + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-native-small", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-app-native-large", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":2,\"adunit\":2,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":300,\"hmin\":300,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":150}}]}" + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-native-large", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-native-small", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":120,\"hmin\":120,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":100}}]}" + }, + "tagid": "app-native-small", + "ext": { + "tagid": "app-native-small", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-app-native-large", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":2,\"adunit\":2,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":300,\"hmin\":300,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":150}}]}" + }, + "tagid": "app-native-large", + "ext": { "tagid": "app-native-large" } + } + ] + }, + "impIDs": ["imp-app-native-small", "imp-app-native-large"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-app-native-small-1", + "impid": "imp-app-native-small", + "price": 1.5, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Small App Native Ad\"}}]}}", + "crid": "crid-app-native-small-1" + }, + { + "id": "bid-app-native-large-1", + "impid": "imp-app-native-large", + "price": 2.75, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Large App Native Ad\"}}]}}", + "crid": "crid-app-native-large-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-app-native-small-1", + "impid": "imp-app-native-small", + "price": 1.5, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Small App Native Ad\"}}]}}", + "crid": "crid-app-native-small-1" + }, + "type": "native" + }, + { + "bid": { + "id": "bid-app-native-large-1", + "impid": "imp-app-native-large", + "price": 2.75, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Large App Native Ad\"}}]}}", + "crid": "crid-app-native-large-1" + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-video.json b/adapters/rtbstack/rtbstacktest/exemplary/app-video.json new file mode 100644 index 00000000000..2f428f3f2db --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-video.json @@ -0,0 +1,156 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-video-small", + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4", "video/webm"], + "minduration": 5, + "maxduration": 30, + "protocols": [2, 5] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-video-small", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-app-video-large", + "video": { + "w": 1280, + "h": 720, + "mimes": ["video/mp4", "video/webm"], + "minduration": 10, + "maxduration": 60, + "protocols": [2, 5, 6] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "app-video-large", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "app": { + "bundle": "com.prebid.app" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-app-video-small", + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4", "video/webm"], + "minduration": 5, + "maxduration": 30, + "protocols": [2, 5] + }, + "tagid": "app-video-small", + "ext": { + "tagid": "app-video-small", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-app-video-large", + "video": { + "w": 1280, + "h": 720, + "mimes": ["video/mp4", "video/webm"], + "minduration": 10, + "maxduration": 60, + "protocols": [2, 5, 6] + }, + "tagid": "app-video-large", + "ext": { "tagid": "app-video-large" } + } + ] + }, + "impIDs": ["imp-app-video-small", "imp-app-video-large"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-app-video-small-1", + "impid": "imp-app-video-small", + "price": 3.0, + "adm": "App Small Video Ad", + "crid": "crid-app-video-small-1" + }, + { + "id": "bid-app-video-large-1", + "impid": "imp-app-video-large", + "price": 5.5, + "adm": "App Large Video Ad", + "crid": "crid-app-video-large-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-app-video-small-1", + "impid": "imp-app-video-small", + "price": 3.0, + "adm": "App Small Video Ad", + "crid": "crid-app-video-small-1" + }, + "type": "video" + }, + { + "bid": { + "id": "bid-app-video-large-1", + "impid": "imp-app-video-large", + "price": 5.5, + "adm": "App Large Video Ad", + "crid": "crid-app-video-large-1" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json b/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json new file mode 100644 index 00000000000..8362951a24f --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json @@ -0,0 +1,177 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "basic", + "customParams": { + "foo": "bar" + } + } + } + }, + + { + "id": "imp-empty-custom", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "empty-custom", + "customParams": {} + } + } + }, + + { + "id": "imp-numeric-bool", + "banner": { + "format": [{ "w": 320, "h": 50 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "numeric-bool", + "customParams": { + "floor": 0.45, + "enabled": true, + "count": 3 + } + } + } + }, + + { + "id": "imp-nested-custom", + "banner": { + "format": [{ "w": 970, "h": 250 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "nested", + "customParams": { + "placement": { + "position": "top", + "sticky": true + }, + "sizes": ["970x250", "728x90"] + } + } + } + }, + + { + "id": "imp-no-custom", + "banner": { + "format": [{ "w": 468, "h": 60 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "no-custom" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "basic", + "ext": { + "tagid": "basic", + "customParams": { "foo": "bar" } + } + }, + + { + "id": "imp-empty-custom", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "tagid": "empty-custom", + "ext": { + "tagid": "empty-custom" + } + }, + + { + "id": "imp-numeric-bool", + "banner": { "format": [{ "w": 320, "h": 50 }] }, + "tagid": "numeric-bool", + "ext": { + "tagid": "numeric-bool", + "customParams": { + "floor": 0.45, + "enabled": true, + "count": 3 + } + } + }, + + { + "id": "imp-nested-custom", + "banner": { "format": [{ "w": 970, "h": 250 }] }, + "tagid": "nested", + "ext": { + "tagid": "nested", + "customParams": { + "placement": { + "position": "top", + "sticky": true + }, + "sizes": ["970x250", "728x90"] + } + } + }, + + { + "id": "imp-no-custom", + "banner": { "format": [{ "w": 468, "h": 60 }] }, + "tagid": "no-custom", + "ext": { + "tagid": "no-custom" + } + } + ] + }, + "impIDs": [ + "imp-basic", + "imp-empty-custom", + "imp-numeric-bool", + "imp-nested-custom", + "imp-no-custom" + ] + }, + "mockResponse": { + "status": 204 + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json b/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json new file mode 100644 index 00000000000..ee36658411d --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json @@ -0,0 +1,140 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "example.com" + }, + "imp": [ + { + "id": "imp-audio-small", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 5, + "maxduration": 30 + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "site-audio-small", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-audio-large", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 15, + "maxduration": 60 + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "site-audio-large", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "example.com" + }, + "imp": [ + { + "id": "imp-audio-small", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 5, + "maxduration": 30 + }, + "tagid": "site-audio-small", + "ext": { + "tagid": "site-audio-small", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-audio-large", + "audio": { + "mimes": ["audio/mpeg", "audio/mp4"], + "minduration": 15, + "maxduration": 60 + }, + "tagid": "site-audio-large", + "ext": { "tagid": "site-audio-large" } + } + ] + }, + "impIDs": ["imp-audio-small", "imp-audio-large"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-site-audio-small-1", + "impid": "imp-audio-small", + "price": 0.75, + "adm": "", + "crid": "crid-site-audio-small-1" + }, + { + "id": "bid-site-audio-large-1", + "impid": "imp-audio-large", + "price": 1.25, + "adm": "", + "crid": "crid-site-audio-large-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-site-audio-small-1", + "impid": "imp-audio-small", + "price": 0.75, + "adm": "", + "crid": "crid-site-audio-small-1" + }, + "type": "audio" + }, + { + "bid": { + "id": "bid-site-audio-large-1", + "impid": "imp-audio-large", + "price": 1.25, + "adm": "", + "crid": "crid-site-audio-large-1" + }, + "type": "audio" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json b/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json new file mode 100644 index 00000000000..c216d60d6fa --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json @@ -0,0 +1,181 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "basic", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-empty-custom", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "empty-custom", + "customParams": {} + } + } + }, + { + "id": "imp-nested-custom", + "banner": { + "format": [{ "w": 970, "h": 250 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "nested", + "customParams": { + "placement": { + "position": "top", + "sticky": true + }, + "sizes": ["970x250", "728x90"] + } + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "basic", + "ext": { + "tagid": "basic", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-empty-custom", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "tagid": "empty-custom", + "ext": { + "tagid": "empty-custom" + } + }, + { + "id": "imp-nested-custom", + "banner": { "format": [{ "w": 970, "h": 250 }] }, + "tagid": "nested", + "ext": { + "tagid": "nested", + "customParams": { + "placement": { + "position": "top", + "sticky": true + }, + "sizes": ["970x250", "728x90"] + } + } + } + ] + }, + "impIDs": ["imp-basic", "imp-empty-custom", "imp-nested-custom"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-basic-1", + "impid": "imp-basic", + "price": 1.25, + "adm": "
Banner 728x90
", + "crid": "crid-basic-1" + }, + { + "id": "bid-empty-1", + "impid": "imp-empty-custom", + "price": 0.75, + "adm": "
Banner 300x250
", + "crid": "crid-empty-1" + }, + { + "id": "bid-nested-1", + "impid": "imp-nested-custom", + "price": 2.50, + "adm": "
Banner 970x250
", + "crid": "crid-nested-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-basic-1", + "impid": "imp-basic", + "price": 1.25, + "adm": "
Banner 728x90
", + "crid": "crid-basic-1" + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-empty-1", + "impid": "imp-empty-custom", + "price": 0.75, + "adm": "
Banner 300x250
", + "crid": "crid-empty-1" + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-nested-1", + "impid": "imp-nested-custom", + "price": 2.50, + "adm": "
Banner 970x250
", + "crid": "crid-nested-1" + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json new file mode 100644 index 00000000000..981d6a1ad5f --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json @@ -0,0 +1,59 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "basic", + "customParams": { + "foo": "bar" + } + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "basic", + "ext": { + "tagid": "basic", + "customParams": { "foo": "bar" } + } + } + ] + }, + "impIDs": [ + "imp-basic" + ] + }, + "mockResponse": { + "status": 204 + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json new file mode 100644 index 00000000000..66a6b82b3c2 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json @@ -0,0 +1,60 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://not-empty.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "basic", + "customParams": { + "foo": "bar" + } + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://not-empty.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "basic", + "ext": { + "tagid": "basic", + "customParams": { "foo": "bar" } + } + } + ] + }, + "impIDs": [ + "imp-basic" + ] + }, + "mockResponse": { + "status": 204 + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-native.json b/adapters/rtbstack/rtbstacktest/exemplary/site-native.json new file mode 100644 index 00000000000..df02faaefa1 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-native.json @@ -0,0 +1,142 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "example.com" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-site-native-small", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":120,\"hmin\":120,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":100}}]}" + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "site-native-small", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-site-native-large", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":2,\"adunit\":2,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":300,\"hmin\":300,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":150}}]}" + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "site-native-large", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "example.com" + }, + "device": { + "ifa": "ec943cb9-61ec-460f-a925-6489c3fcc4e3" + }, + "imp": [ + { + "id": "imp-site-native-small", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":120,\"hmin\":120,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":100}}]}" + }, + "tagid": "site-native-small", + "ext": { + "tagid": "site-native-small", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-site-native-large", + "native": { + "ver": "1.1", + "request": "{\"ver\":\"1.0\",\"layout\":2,\"adunit\":2,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":300,\"hmin\":300,\"mimes\":[\"image/jpeg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":150}}]}" + }, + "tagid": "site-native-large", + "ext": { "tagid": "site-native-large" } + } + ] + }, + "impIDs": ["imp-site-native-small", "imp-site-native-large"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-site-native-small-1", + "impid": "imp-site-native-small", + "price": 1.5, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Small Native Ad\"}}]}}", + "crid": "crid-site-native-small-1" + }, + { + "id": "bid-site-native-large-1", + "impid": "imp-site-native-large", + "price": 2.75, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Large Native Ad\"}}]}}", + "crid": "crid-site-native-large-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-site-native-small-1", + "impid": "imp-site-native-small", + "price": 1.5, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Small Native Ad\"}}]}}", + "crid": "crid-site-native-small-1" + }, + "type": "native" + }, + { + "bid": { + "id": "bid-site-native-large-1", + "impid": "imp-site-native-large", + "price": 2.75, + "adm": "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Large Native Ad\"}}]}}", + "crid": "crid-site-native-large-1" + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-video.json b/adapters/rtbstack/rtbstacktest/exemplary/site-video.json new file mode 100644 index 00000000000..015203326a4 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-video.json @@ -0,0 +1,152 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "example.com" + }, + "imp": [ + { + "id": "imp-video-small", + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4", "video/webm"], + "minduration": 5, + "maxduration": 30, + "protocols": [2, 5] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "video-small", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-video-large", + "video": { + "w": 1280, + "h": 720, + "mimes": ["video/mp4", "video/webm"], + "minduration": 10, + "maxduration": 60, + "protocols": [2, 5, 6] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "video-large", + "customParams": {} + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "example.com" + }, + "imp": [ + { + "id": "imp-video-small", + "video": { + "w": 640, + "h": 360, + "mimes": ["video/mp4", "video/webm"], + "minduration": 5, + "maxduration": 30, + "protocols": [2, 5] + }, + "tagid": "video-small", + "ext": { + "tagid": "video-small", + "customParams": { "foo": "bar" } + } + }, + { + "id": "imp-video-large", + "video": { + "w": 1280, + "h": 720, + "mimes": ["video/mp4", "video/webm"], + "minduration": 10, + "maxduration": 60, + "protocols": [2, 5, 6] + }, + "tagid": "video-large", + "ext": { "tagid": "video-large" } + } + ] + }, + "impIDs": ["imp-video-small", "imp-video-large"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "rtbstack", + "bid": [ + { + "id": "bid-video-small-1", + "impid": "imp-video-small", + "price": 3.00, + "adm": "Small Video Ad", + "crid": "crid-video-small-1" + }, + { + "id": "bid-video-large-1", + "impid": "imp-video-large", + "price": 5.50, + "adm": "Large Video Ad", + "crid": "crid-video-large-1" + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-video-small-1", + "impid": "imp-video-small", + "price": 3.0, + "adm": "Small Video Ad", + "crid": "crid-video-small-1" + }, + "type": "video" + }, + { + "bid": { + "id": "bid-video-large-1", + "impid": "imp-video-large", + "price": 5.5, + "adm": "Large Video Ad", + "crid": "crid-video-large-1" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/supplemental/bad-imp.json b/adapters/rtbstack/rtbstacktest/supplemental/bad-imp.json new file mode 100644 index 00000000000..7fb55166c3f --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/supplemental/bad-imp.json @@ -0,0 +1,29 @@ +{ + "mockBidRequest": { + "id": "test-request-error", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-invalid", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": "invalid-json" + } + ] + }, + + "httpCalls": [], + + "expectedMakeRequestsErrors": [ + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json b/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json new file mode 100644 index 00000000000..6f33c73c47f --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json @@ -0,0 +1,70 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "test-banner", + "customParams": { + "foo": "bar" + } + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "tagid": "test-banner", + "ext": { + "tagid": "test-banner", + "customParams": { + "foo": "bar" + } + } + } + ] + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": "{\"id\"data.lost" + } + } + ], + + "expectedMakeBidsErrors": [ + { + "value": "expect { or n, but found \"", + "comparison": "literal" + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/supplemental/status-204.json b/adapters/rtbstack/rtbstacktest/supplemental/status-204.json new file mode 100644 index 00000000000..1df1ad35fc9 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/supplemental/status-204.json @@ -0,0 +1,58 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "basic", + "customParams": { + "foo": "bar" + } + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "basic", + "ext": { + "tagid": "basic", + "customParams": { "foo": "bar" } + } + } + ] + }, + "impIDs": ["imp-basic"] + }, + "mockResponse": { + "status": 204 + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/rtbstack/rtbstacktest/supplemental/status-400.json b/adapters/rtbstack/rtbstacktest/supplemental/status-400.json new file mode 100644 index 00000000000..2065c48bca5 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/supplemental/status-400.json @@ -0,0 +1,64 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "basic", + "customParams": { + "foo": "bar" + } + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-basic", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "basic", + "ext": { + "tagid": "basic", + "customParams": { "foo": "bar" } + } + } + ] + }, + "impIDs": ["imp-basic"] + }, + "mockResponse": { + "status": 400 + } + } + ], + + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400", + "comparison": "literal" + } + ] +} diff --git a/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json b/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json new file mode 100644 index 00000000000..97f39c2be45 --- /dev/null +++ b/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json @@ -0,0 +1,69 @@ +{ + "mockBidRequest": { + "id": "test-request-partial", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-valid", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "ext": { + "bidder": { + "endpoint": "http://test.rtb-stack.com", + "tagId": "valid-tag", + "customParams": { + "foo": "bar" + } + } + } + }, + { + "id": "imp-invalid", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": "invalid-json" + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://test.rtb-stack.com", + "body": { + "id": "test-request-partial", + "site": { + "page": "https://example.com", + "domain": "https://example.com" + }, + "imp": [ + { + "id": "imp-valid", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "tagid": "valid-tag", + "ext": { + "tagid": "valid-tag", + "customParams": { + "foo": "bar" + } + } + } + ] + }, + "impIDs": ["imp-valid"] + }, + "mockResponse": { + "status": 204 + } + } + ], + + "expectedMakeRequestsErrors": [], + + "expectedBidResponses": [] +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 9a2aaa0bd21..24031ebbc25 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -198,6 +198,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/rise" "github.com/prebid/prebid-server/v3/adapters/roulax" "github.com/prebid/prebid-server/v3/adapters/rtbhouse" + "github.com/prebid/prebid-server/v3/adapters/rtbstack" "github.com/prebid/prebid-server/v3/adapters/rubicon" salunamedia "github.com/prebid/prebid-server/v3/adapters/sa_lunamedia" "github.com/prebid/prebid-server/v3/adapters/seedingAlliance" @@ -528,5 +529,6 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderZeroClickFraud: zeroclickfraud.Builder, openrtb_ext.BidderZetaGlobalSsp: zeta_global_ssp.Builder, openrtb_ext.BidderZmaticoo: zmaticoo.Builder, + openrtb_ext.BidderRTBStack: rtbstack.Builder, } } diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 8cd543c1f16..95b6d0b190f 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -278,6 +278,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderZeroClickFraud, BidderZetaGlobalSsp, BidderZmaticoo, + BidderRTBStack, } func GetAliasBidderToParent() map[BidderName]BidderName { @@ -651,6 +652,7 @@ const ( BidderZeroClickFraud BidderName = "zeroclickfraud" BidderZetaGlobalSsp BidderName = "zeta_global_ssp" BidderZmaticoo BidderName = "zmaticoo" + BidderRTBStack BidderName = "rtbstack" ) // CoreBidderNames returns a slice of all core bidders. diff --git a/openrtb_ext/imp_rtbstack.go b/openrtb_ext/imp_rtbstack.go new file mode 100644 index 00000000000..47411bf79b5 --- /dev/null +++ b/openrtb_ext/imp_rtbstack.go @@ -0,0 +1,7 @@ +package openrtb_ext + +type ExtImpRTBStack struct { + Endpoint string `json:"endpoint,omitempty"` + TagId string `json:"tagid,omitempty"` + CustomParams map[string]interface{} `json:"customParams,omitempty"` +} diff --git a/static/bidder-info/rtbstack.yaml b/static/bidder-info/rtbstack.yaml new file mode 100644 index 00000000000..61051fae6c4 --- /dev/null +++ b/static/bidder-info/rtbstack.yaml @@ -0,0 +1,16 @@ +endpoint: "http://{{.Host}}" +maintainer: + email: "prebid@admixer.net" +gvlVendorID: 511 +capabilities: + site: + mediaTypes: + - banner + - video + - native + + app: + mediaTypes: + - banner + - video + - native \ No newline at end of file diff --git a/static/bidder-params/rtbstack.json b/static/bidder-params/rtbstack.json new file mode 100644 index 00000000000..001be726db0 --- /dev/null +++ b/static/bidder-params/rtbstack.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "RTBStack Adapter Params", + "description": "A schema which validates params accepted by the RTBStack adapter", + + "type": "object", + "properties": { + "endpoint": { + "type": "string", + "description": "Url provided for pbs auction." + }, + "tagId": { + "type": "string", + "description": "AdUnit tag id." + }, + "customParams": { + "type": "object", + "description": "Custom values for targeting." + } + }, + + "required": ["endpoint", "tagId"] +} \ No newline at end of file From 502aaa5691258286d3860b438b737ef620e2616e Mon Sep 17 00:00:00 2001 From: Volokha Date: Tue, 10 Feb 2026 15:15:39 +0200 Subject: [PATCH 2/6] remove imp copy --- adapters/rtbstack/rtbstack.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adapters/rtbstack/rtbstack.go b/adapters/rtbstack/rtbstack.go index 5c5c5e6fdce..37a2df31498 100644 --- a/adapters/rtbstack/rtbstack.go +++ b/adapters/rtbstack/rtbstack.go @@ -48,9 +48,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var errs []error var validImps []*impCtx - for i := range request.Imp { - imp := request.Imp[i] - + for _, imp := range request.Imp { ext, err := preprocessImp(&imp) if err != nil { errs = append(errs, err) From 60b451c1b8ed45392850893ca206982ed8fc9052 Mon Sep 17 00:00:00 2001 From: Volokha Date: Tue, 10 Feb 2026 15:42:59 +0200 Subject: [PATCH 3/6] add bidderName to appropriate place --- openrtb_ext/bidders.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 95b6d0b190f..97c2de71d38 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -216,6 +216,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderRise, BidderRoulax, BidderRTBHouse, + BidderRTBStack, BidderRubicon, BidderSeedingAlliance, BidderSeedtag, @@ -278,7 +279,6 @@ var coreBidderNames []BidderName = []BidderName{ BidderZeroClickFraud, BidderZetaGlobalSsp, BidderZmaticoo, - BidderRTBStack, } func GetAliasBidderToParent() map[BidderName]BidderName { @@ -590,6 +590,7 @@ const ( BidderRise BidderName = "rise" BidderRoulax BidderName = "roulax" BidderRTBHouse BidderName = "rtbhouse" + BidderRTBStack BidderName = "rtbstack" BidderRubicon BidderName = "rubicon" BidderSeedingAlliance BidderName = "seedingAlliance" BidderSeedtag BidderName = "seedtag" @@ -652,7 +653,6 @@ const ( BidderZeroClickFraud BidderName = "zeroclickfraud" BidderZetaGlobalSsp BidderName = "zeta_global_ssp" BidderZmaticoo BidderName = "zmaticoo" - BidderRTBStack BidderName = "rtbstack" ) // CoreBidderNames returns a slice of all core bidders. From 5a9b3fe799baa192a8dd9e10eb470e2f1687c95e Mon Sep 17 00:00:00 2001 From: Volokha Date: Tue, 10 Feb 2026 15:44:48 +0200 Subject: [PATCH 4/6] add audio to supported media types --- static/bidder-info/rtbstack.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/static/bidder-info/rtbstack.yaml b/static/bidder-info/rtbstack.yaml index 61051fae6c4..2cf571afbd6 100644 --- a/static/bidder-info/rtbstack.yaml +++ b/static/bidder-info/rtbstack.yaml @@ -8,9 +8,10 @@ capabilities: - banner - video - native - + - audio app: mediaTypes: - banner - video - - native \ No newline at end of file + - native + - audio \ No newline at end of file From f6d7c9728c3986da8f508a80bcea00e9038741ab Mon Sep 17 00:00:00 2001 From: Volokha Date: Tue, 10 Feb 2026 15:48:04 +0200 Subject: [PATCH 5/6] order import --- adapters/rtbstack/rtbstack.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/adapters/rtbstack/rtbstack.go b/adapters/rtbstack/rtbstack.go index 37a2df31498..ea5fe5641ad 100644 --- a/adapters/rtbstack/rtbstack.go +++ b/adapters/rtbstack/rtbstack.go @@ -3,14 +3,15 @@ package rtbstack import ( "encoding/json" "fmt" + "net/http" + "strings" + "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" - "net/http" - "strings" ) const endpointMacro = "http://{{.Host}}" From 11dbfcddf99742895af2f338b0fb4f6a7005ab09 Mon Sep 17 00:00:00 2001 From: Volokha Date: Fri, 13 Feb 2026 12:38:11 +0200 Subject: [PATCH 6/6] added host and query instead of endpoint for rtb-stack backend url --- adapters/rtbstack/rtbstack.go | 41 +++++++++++++++---- adapters/rtbstack/rtbstack_test.go | 2 +- .../rtbstacktest/exemplary/app-audio.json | 8 ++-- .../rtbstacktest/exemplary/app-banner.json | 8 ++-- .../rtbstacktest/exemplary/app-native.json | 8 ++-- .../rtbstacktest/exemplary/app-video.json | 8 ++-- .../exemplary/optional-params.json | 17 +++++--- .../rtbstacktest/exemplary/site-audio.json | 8 ++-- .../rtbstacktest/exemplary/site-banner.json | 11 +++-- .../exemplary/site-domain-empty-mutation.json | 5 ++- .../exemplary/site-domain-mutation.json | 5 ++- .../rtbstacktest/exemplary/site-native.json | 8 ++-- .../rtbstacktest/exemplary/site-video.json | 8 ++-- .../supplemental/bad-response.json | 5 ++- .../rtbstacktest/supplemental/status-204.json | 5 ++- .../rtbstacktest/supplemental/status-400.json | 5 ++- .../supplemental/two-imps-one-is-bad.json | 5 ++- openrtb_ext/imp_rtbstack.go | 3 +- static/bidder-info/rtbstack.yaml | 2 +- static/bidder-params/rtbstack.json | 10 +++-- 20 files changed, 116 insertions(+), 56 deletions(-) diff --git a/adapters/rtbstack/rtbstack.go b/adapters/rtbstack/rtbstack.go index ea5fe5641ad..9baa2513b65 100644 --- a/adapters/rtbstack/rtbstack.go +++ b/adapters/rtbstack/rtbstack.go @@ -5,19 +5,19 @@ import ( "fmt" "net/http" "strings" + "text/template" "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/macros" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" ) -const endpointMacro = "http://{{.Host}}" - type adapter struct { - endpoint string + endpoint *template.Template } // impCtx represents the context containing an OpenRTB impression and its corresponding RTBStack extension configuration. @@ -33,8 +33,13 @@ type extImpRTBStack struct { } func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + tpl, err := template.New("endpointTemplate").Parse(config.Endpoint) + if err != nil { + return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) + } + bidder := &adapter{ - endpoint: config.Endpoint, + endpoint: tpl, } return bidder, nil } @@ -71,7 +76,10 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E request.Imp = append(request.Imp, v.imp) } - endpoint := a.buildEndpointURL(validImps[0].rtbStackExt) + endpoint, err := a.buildEndpointURL(validImps[0].rtbStackExt) + if err != nil { + return nil, []error{err} + } var newRequest openrtb2.BidRequest newRequest = *request @@ -134,8 +142,27 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest return bidResponse, []error{} } -func (a *adapter) buildEndpointURL(ext *openrtb_ext.ExtImpRTBStack) string { - return strings.Replace(a.endpoint, endpointMacro, ext.Endpoint, -1) +func (a *adapter) buildEndpointURL(ext *openrtb_ext.ExtImpRTBStack) (string, error) { + // Normalize host to avoid accidental protocol prefixes and domains accidentally included + host := ext.Host + host = strings.TrimPrefix(host, "http://") + host = strings.TrimPrefix(host, "https://") + + endpointParams := macros.EndpointTemplateParams{Host: host} + baseURL, err := macros.ResolveMacros(a.endpoint, endpointParams) + if err != nil { + return "", fmt.Errorf("unable to resolve endpoint: %v", err) + } + + if ext.Query == "" { + return baseURL, nil + } + + if strings.HasPrefix(ext.Query, "/") { + return baseURL + ext.Query, nil + } + + return baseURL + "/" + ext.Query, nil } func preprocessImp( diff --git a/adapters/rtbstack/rtbstack_test.go b/adapters/rtbstack/rtbstack_test.go index a55841f5183..7f31f0e562f 100644 --- a/adapters/rtbstack/rtbstack_test.go +++ b/adapters/rtbstack/rtbstack_test.go @@ -9,7 +9,7 @@ import ( func TestJsonSamples(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.BidderRTBStack, config.Adapter{ - Endpoint: "http://{{.Host}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + Endpoint: "https://{{.Host}}.rtb-stack.com"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) if buildErr != nil { t.Fatalf("Builder returned unexpected error %v", buildErr) diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json b/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json index 939c54f2526..63865362e96 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-audio.json @@ -17,7 +17,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-audio-short", "customParams": { "foo": "bar" @@ -34,7 +35,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-audio-long", "customParams": {} } @@ -46,7 +48,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "app": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json b/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json index 50c095395cb..9799eafa2ec 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-banner.json @@ -15,7 +15,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-basic", "customParams": { "foo": "bar" @@ -30,7 +31,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-large", "customParams": {} } @@ -42,7 +44,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "app": { "bundle": "com.prebid.app" }, diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-native.json b/adapters/rtbstack/rtbstacktest/exemplary/app-native.json index 7a7f3974721..ffb9c9ca44c 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/app-native.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-native.json @@ -16,7 +16,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-native-small", "customParams": { "foo": "bar" @@ -32,7 +33,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-native-large", "customParams": {} } @@ -44,7 +46,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "app": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/app-video.json b/adapters/rtbstack/rtbstacktest/exemplary/app-video.json index 2f428f3f2db..a050b608c44 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/app-video.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/app-video.json @@ -20,7 +20,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-video-small", "customParams": { "foo": "bar" @@ -40,7 +41,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "app-video-large", "customParams": {} } @@ -52,7 +54,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "app": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json b/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json index 8362951a24f..53de9ed9732 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/optional-params.json @@ -13,7 +13,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "basic", "customParams": { "foo": "bar" @@ -29,7 +30,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "empty-custom", "customParams": {} } @@ -43,7 +45,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "numeric-bool", "customParams": { "floor": 0.45, @@ -61,7 +64,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "nested", "customParams": { "placement": { @@ -81,7 +85,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "no-custom" } } @@ -92,7 +97,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json b/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json index ee36658411d..a3b4a18c177 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-audio.json @@ -15,7 +15,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "site-audio-small", "customParams": { "foo": "bar" @@ -32,7 +33,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "site-audio-large", "customParams": {} } @@ -44,7 +46,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json b/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json index c216d60d6fa..c7c753c6cbc 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-banner.json @@ -13,7 +13,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "basic", "customParams": { "foo": "bar" @@ -28,7 +29,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "empty-custom", "customParams": {} } @@ -41,7 +43,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "nested", "customParams": { "placement": { @@ -59,7 +62,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json index 981d6a1ad5f..a878780e27a 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-empty-mutation.json @@ -12,7 +12,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "basic", "customParams": { "foo": "bar" @@ -26,7 +27,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json index 66a6b82b3c2..61d5ac611eb 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-domain-mutation.json @@ -13,7 +13,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "basic", "customParams": { "foo": "bar" @@ -27,7 +28,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-native.json b/adapters/rtbstack/rtbstacktest/exemplary/site-native.json index df02faaefa1..ff5f05afdb7 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/site-native.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-native.json @@ -17,7 +17,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "site-native-small", "customParams": { "foo": "bar" @@ -33,7 +34,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "site-native-large", "customParams": {} } @@ -45,7 +47,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/exemplary/site-video.json b/adapters/rtbstack/rtbstacktest/exemplary/site-video.json index 015203326a4..b6baf30f0bb 100644 --- a/adapters/rtbstack/rtbstacktest/exemplary/site-video.json +++ b/adapters/rtbstack/rtbstacktest/exemplary/site-video.json @@ -18,7 +18,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "video-small", "customParams": { "foo": "bar" @@ -38,7 +39,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "video-large", "customParams": {} } @@ -50,7 +52,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json b/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json index 6f33c73c47f..2e2c515f583 100644 --- a/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json +++ b/adapters/rtbstack/rtbstacktest/supplemental/bad-response.json @@ -14,7 +14,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "test-banner", "customParams": { "foo": "bar" @@ -28,7 +29,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "imp": [ diff --git a/adapters/rtbstack/rtbstacktest/supplemental/status-204.json b/adapters/rtbstack/rtbstacktest/supplemental/status-204.json index 1df1ad35fc9..8b59c7bf474 100644 --- a/adapters/rtbstack/rtbstacktest/supplemental/status-204.json +++ b/adapters/rtbstack/rtbstacktest/supplemental/status-204.json @@ -13,7 +13,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "basic", "customParams": { "foo": "bar" @@ -27,7 +28,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/supplemental/status-400.json b/adapters/rtbstack/rtbstacktest/supplemental/status-400.json index 2065c48bca5..a46aa75c8f7 100644 --- a/adapters/rtbstack/rtbstacktest/supplemental/status-400.json +++ b/adapters/rtbstack/rtbstacktest/supplemental/status-400.json @@ -13,7 +13,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "basic", "customParams": { "foo": "bar" @@ -27,7 +28,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-id", "site": { diff --git a/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json b/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json index 97f39c2be45..28d53b71f87 100644 --- a/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json +++ b/adapters/rtbstack/rtbstacktest/supplemental/two-imps-one-is-bad.json @@ -13,7 +13,8 @@ }, "ext": { "bidder": { - "endpoint": "http://test.rtb-stack.com", + "host": "test", + "query": "prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "tagId": "valid-tag", "customParams": { "foo": "bar" @@ -34,7 +35,7 @@ "httpCalls": [ { "expectedRequest": { - "uri": "http://test.rtb-stack.com", + "uri": "https://test.rtb-stack.com/prebid?client=c4527281-5aa5-4c8e-bc53-a80bb3f99470&endpoint=309&ssp=145", "body": { "id": "test-request-partial", "site": { diff --git a/openrtb_ext/imp_rtbstack.go b/openrtb_ext/imp_rtbstack.go index 47411bf79b5..78a87ebe345 100644 --- a/openrtb_ext/imp_rtbstack.go +++ b/openrtb_ext/imp_rtbstack.go @@ -1,7 +1,8 @@ package openrtb_ext type ExtImpRTBStack struct { - Endpoint string `json:"endpoint,omitempty"` + Host string `json:"host,omitempty"` + Query string `json:"query,omitempty"` TagId string `json:"tagid,omitempty"` CustomParams map[string]interface{} `json:"customParams,omitempty"` } diff --git a/static/bidder-info/rtbstack.yaml b/static/bidder-info/rtbstack.yaml index 2cf571afbd6..af397e5c872 100644 --- a/static/bidder-info/rtbstack.yaml +++ b/static/bidder-info/rtbstack.yaml @@ -1,4 +1,4 @@ -endpoint: "http://{{.Host}}" +endpoint: "https://{{.Host}}.rtb-stack.com" maintainer: email: "prebid@admixer.net" gvlVendorID: 511 diff --git a/static/bidder-params/rtbstack.json b/static/bidder-params/rtbstack.json index 001be726db0..30d1ca0cf3a 100644 --- a/static/bidder-params/rtbstack.json +++ b/static/bidder-params/rtbstack.json @@ -5,9 +5,13 @@ "type": "object", "properties": { - "endpoint": { + "host": { "type": "string", - "description": "Url provided for pbs auction." + "description": "Subdomain host used for RTBStack requests." + }, + "query": { + "type": "string", + "description": "Path and query string appended to the RTBStack endpoint." }, "tagId": { "type": "string", @@ -19,5 +23,5 @@ } }, - "required": ["endpoint", "tagId"] + "required": ["host", "query", "tagId"] } \ No newline at end of file