From b4a6ab3a7e6bc91bac5bad00720764649c57639b Mon Sep 17 00:00:00 2001 From: "chinmay.b" Date: Mon, 8 Apr 2024 17:30:26 +0530 Subject: [PATCH] New Adapter: Trustedstack --- adapters/trustedstack/params_test.go | 54 +++++++ adapters/trustedstack/trustedstack.go | 121 ++++++++++++++++ adapters/trustedstack/trustedstack_test.go | 31 ++++ .../exemplary/multi-format.json | 83 +++++++++++ .../exemplary/multi-imps.json | 132 ++++++++++++++++++ .../trustedstacktest/exemplary/no-bid.json | 60 ++++++++ .../exemplary/optional-params.json | 62 ++++++++ .../exemplary/simple-banner.json | 98 +++++++++++++ .../exemplary/simple-video.json | 101 ++++++++++++++ ...valid-req-400-status-code-bad-request.json | 97 +++++++++++++ .../valid-req-200-bid-response-from-mnet.json | 130 +++++++++++++++++ .../valid-req-204-response-from-mnet.json | 66 +++++++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_trustedstack.go | 6 + static/bidder-info/trustedstack.yaml | 24 ++++ static/bidder-params/trustedstack.json | 22 +++ 17 files changed, 1091 insertions(+) create mode 100644 adapters/trustedstack/params_test.go create mode 100644 adapters/trustedstack/trustedstack.go create mode 100644 adapters/trustedstack/trustedstack_test.go create mode 100644 adapters/trustedstack/trustedstacktest/exemplary/multi-format.json create mode 100644 adapters/trustedstack/trustedstacktest/exemplary/multi-imps.json create mode 100644 adapters/trustedstack/trustedstacktest/exemplary/no-bid.json create mode 100644 adapters/trustedstack/trustedstacktest/exemplary/optional-params.json create mode 100644 adapters/trustedstack/trustedstacktest/exemplary/simple-banner.json create mode 100644 adapters/trustedstack/trustedstacktest/exemplary/simple-video.json create mode 100644 adapters/trustedstack/trustedstacktest/supplemental/invalid-req-400-status-code-bad-request.json create mode 100644 adapters/trustedstack/trustedstacktest/supplemental/valid-req-200-bid-response-from-mnet.json create mode 100755 adapters/trustedstack/trustedstacktest/supplemental/valid-req-204-response-from-mnet.json create mode 100644 openrtb_ext/imp_trustedstack.go create mode 100644 static/bidder-info/trustedstack.yaml create mode 100644 static/bidder-params/trustedstack.json diff --git a/adapters/trustedstack/params_test.go b/adapters/trustedstack/params_test.go new file mode 100644 index 00000000000..55812126cae --- /dev/null +++ b/adapters/trustedstack/params_test.go @@ -0,0 +1,54 @@ +package trustedstack + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +// This file actually intends to test static/bidder-params/trustedstack.json +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, validParam := range validParams { + if err := validator.Validate(openrtb_ext.BidderTrustedstack, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected trustedstack params: %s", validParam) + } + } +} + +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, invalidParam := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderTrustedstack, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"cid":"123", "crid":"1234"}`, +} + +var invalidParams = []string{ + ``, + `null`, + `true`, + `5`, + `4.2`, + `[]`, + `{}`, + `{"cid":"", "crid":""}`, + `{"cid":"only cid is present"}`, + `{"crid":"only crid is present"}`, + `{"ccid":"123","ccrid":"123"}`, + `{"aid":123, "placementId":"123", "siteId":"321"}`, +} diff --git a/adapters/trustedstack/trustedstack.go b/adapters/trustedstack/trustedstack.go new file mode 100644 index 00000000000..f6bf9d08864 --- /dev/null +++ b/adapters/trustedstack/trustedstack.go @@ -0,0 +1,121 @@ +package trustedstack + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v2/config" + "github.com/prebid/prebid-server/v2/errortypes" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +type adapter struct { + endpoint string +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var errs []error + + reqJson, err := json.Marshal(request) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + + return []*adapters.RequestData{{ + Method: "POST", + Uri: a.endpoint, + Body: reqJson, + Headers: headers, + }}, errs +} + +func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + var errs []error + + if response.StatusCode == http.StatusNoContent { + return nil, nil + } + + if response.StatusCode == http.StatusBadRequest { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), + }} + } + + if response.StatusCode != http.StatusOK { + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), + }} + } + + var bidResp openrtb2.BidResponse + + if err := json.Unmarshal(response.Body, &bidResp); err != nil { + return nil, []error{err} + } + + bidResponse := adapters.NewBidderResponse() + + for _, sb := range bidResp.SeatBid { + for i := range sb.Bid { + bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp) + if err != nil { + errs = append(errs, err) + } else { + b := &adapters.TypedBid{ + Bid: &sb.Bid[i], + BidType: bidType, + } + bidResponse.Bids = append(bidResponse.Bids, b) + } + } + } + return bidResponse, errs +} + +// Builder builds a new instance of the Trustedstack adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + url := buildEndpoint(config.Endpoint, config.ExtraAdapterInfo) + return &adapter{ + endpoint: url, + }, nil +} + +func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) { + mediaType := openrtb_ext.BidTypeBanner + for _, imp := range imps { + if imp.ID == impID { + if imp.Banner == nil && imp.Video != nil { + mediaType = openrtb_ext.BidTypeVideo + } + return mediaType, nil + } + } + + return "", &errortypes.BadInput{ + Message: fmt.Sprintf("Failed to find impression \"%s\" ", impID), + } +} + +func buildEndpoint(mnetUrl, hostUrl string) string { + + if len(hostUrl) == 0 { + return mnetUrl + } + urlObject, err := url.Parse(mnetUrl) + if err != nil { + return mnetUrl + } + values := urlObject.Query() + values.Add("src", hostUrl) + urlObject.RawQuery = values.Encode() + return urlObject.String() +} diff --git a/adapters/trustedstack/trustedstack_test.go b/adapters/trustedstack/trustedstack_test.go new file mode 100644 index 00000000000..c2e1742c55c --- /dev/null +++ b/adapters/trustedstack/trustedstack_test.go @@ -0,0 +1,31 @@ +package trustedstack + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/prebid/prebid-server/v2/adapters/adapterstest" + "github.com/prebid/prebid-server/v2/config" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderTrustedstack, config.Adapter{ + Endpoint: "https://example.trustedstack.com/rtb/prebid", + ExtraAdapterInfo: "http://localhost:8080/extrnal_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, "trustedstacktest", bidder) +} + +func TestEndpointTemplateMalformed(t *testing.T) { + _, buildErr := Builder(openrtb_ext.BidderTrustedstack, config.Adapter{ + Endpoint: "{{Malformed}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + assert.Nil(t, buildErr) +} diff --git a/adapters/trustedstack/trustedstacktest/exemplary/multi-format.json b/adapters/trustedstack/trustedstacktest/exemplary/multi-format.json new file mode 100644 index 00000000000..a6fd49016dc --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/exemplary/multi-format.json @@ -0,0 +1,83 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 320, + "h": 480 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 320, + "h": 480 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + } + }, + + "mockResponse": { + "status": 204, + "body": "" + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/trustedstack/trustedstacktest/exemplary/multi-imps.json b/adapters/trustedstack/trustedstacktest/exemplary/multi-imps.json new file mode 100644 index 00000000000..4316e5526cc --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/exemplary/multi-imps.json @@ -0,0 +1,132 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + }, + { + "id": "2", + "banner": { + "format": [ + { + "w": 300, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSESHA", + "crid": "9999999789" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + }, + { + "id": "2", + "banner": { + "format": [ + { + "w": 300, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSESHA", + "crid": "9999999789" + } + } + } + ] + } + }, + + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "trustedstack", + "bid": [ + { + "id": "test-bid-id", + "impid": "1", + "price": 1.50, + "adm": "some-test-ad", + "crid": "test-crid", + "h": 50, + "w": 320 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-bid-id", + "impid": "1", + "price": 1.50, + "adm": "some-test-ad", + "crid": "test-crid", + "w": 320, + "h": 50 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/trustedstack/trustedstacktest/exemplary/no-bid.json b/adapters/trustedstack/trustedstacktest/exemplary/no-bid.json new file mode 100644 index 00000000000..8e4c1e380d3 --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/exemplary/no-bid.json @@ -0,0 +1,60 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/trustedstack/trustedstacktest/exemplary/optional-params.json b/adapters/trustedstack/trustedstacktest/exemplary/optional-params.json new file mode 100644 index 00000000000..ae115c7f830 --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/exemplary/optional-params.json @@ -0,0 +1,62 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999", + "tagid_src": "ext" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999", + "tagid_src": "ext" + } + } + } + ] + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + + "expectedBidResponses": [] +} diff --git a/adapters/trustedstack/trustedstacktest/exemplary/simple-banner.json b/adapters/trustedstack/trustedstacktest/exemplary/simple-banner.json new file mode 100644 index 00000000000..affa1b44292 --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/exemplary/simple-banner.json @@ -0,0 +1,98 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "banner": { + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + } + }, + + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "trustedstack", + "bid": [ + { + "id": "test-bid-id", + "impid": "1", + "price": 1.50, + "adm": "some-test-ad", + "crid": "test-crid", + "h": 50, + "w": 320 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-bid-id", + "impid": "1", + "price": 1.50, + "adm": "some-test-ad", + "crid": "test-crid", + "w": 320, + "h": 50 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/trustedstack/trustedstacktest/exemplary/simple-video.json b/adapters/trustedstack/trustedstacktest/exemplary/simple-video.json new file mode 100644 index 00000000000..8ad14228d3e --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/exemplary/simple-video.json @@ -0,0 +1,101 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 320, + "h": 480 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "1", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 320, + "h": 480 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "seat": "trustedstack", + "bid": [ + { + "id": "test-bid-id", + "impid": "1", + "price": 2.50, + "adm": "some-test-ad", + "crid": "test-crid", + "w": 320, + "h": 480 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-bid-id", + "impid": "1", + "price": 2.50, + "adm": "some-test-ad", + "crid": "test-crid", + "w": 320, + "h": 480 + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/trustedstack/trustedstacktest/supplemental/invalid-req-400-status-code-bad-request.json b/adapters/trustedstack/trustedstacktest/supplemental/invalid-req-400-status-code-bad-request.json new file mode 100644 index 00000000000..8c8fa7a36f5 --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/supplemental/invalid-req-400-status-code-bad-request.json @@ -0,0 +1,97 @@ + +{ + "mockBidRequest": { + "id": "some-request-id", + "tmax": 1000, + "user": { + "buyeruid": "0000-000-000-0000" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "imp": [ + { + "id": "some-impression-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480, + "minduration": 120, + "maxduration": 150 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ] + }, + + "httpCalls": [{ + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480, + "minduration": 120, + "maxduration": 150 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ], + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "user": { + "buyeruid": "0000-000-000-0000" + }, + "tmax": 1000 + } + }, + "mockResponse": { + "status": 400 + } + }], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/trustedstack/trustedstacktest/supplemental/valid-req-200-bid-response-from-mnet.json b/adapters/trustedstack/trustedstacktest/supplemental/valid-req-200-bid-response-from-mnet.json new file mode 100644 index 00000000000..666cc3e485c --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/supplemental/valid-req-200-bid-response-from-mnet.json @@ -0,0 +1,130 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "193.168.244.1" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "regs": { + "gdpr": 0 + } + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "193.168.244.1" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "regs": { + "gdpr": 0 + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "tid", + "seatbid": [ + { + "seat": "trustedstack", + "bid": [ + { + "id": "randomid", + "impid": "test-imp-id", + "price": 0.500000, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300 + } + ] + } + ], + "bidid": "bid01" + } + } + }], + + "expectedBidResponses": [{ + "currency": "USD", + "bids": [{ + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 0.500000, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300 + }, + "type": "banner" + }] + }] +} diff --git a/adapters/trustedstack/trustedstacktest/supplemental/valid-req-204-response-from-mnet.json b/adapters/trustedstack/trustedstacktest/supplemental/valid-req-204-response-from-mnet.json new file mode 100755 index 00000000000..fd8592dce33 --- /dev/null +++ b/adapters/trustedstack/trustedstacktest/supplemental/valid-req-204-response-from-mnet.json @@ -0,0 +1,66 @@ +{ + "mockBidRequest": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.1", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + }, + "imp": [ + { + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + }, + "banner": { + "w": 320, + "h": 50 + }, + "id": "imp-id" + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://example.trustedstack.com/rtb/prebid?src=http%3A%2F%2Flocalhost%3A8080%2Fextrnal_url", + "body": { + "app": { + "bundle": "com.example.app" + }, + "id": "req-id", + "device": { + "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d", + "ip": "1.1.1.1", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36" + }, + "imp": [ + { + "ext": { + "bidder": { + "cid": "8CUTSTCID", + "crid": "999999999" + } + }, + "banner": { + "w": 320, + "h": 50 + }, + "id": "imp-id" + } + ] + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 416bd164445..f510df4a6e1 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -179,6 +179,7 @@ import ( "github.com/prebid/prebid-server/v2/adapters/trafficgate" "github.com/prebid/prebid-server/v2/adapters/triplelift" "github.com/prebid/prebid-server/v2/adapters/triplelift_native" + "github.com/prebid/prebid-server/v2/adapters/trustedstack" "github.com/prebid/prebid-server/v2/adapters/ucfunnel" "github.com/prebid/prebid-server/v2/adapters/undertone" "github.com/prebid/prebid-server/v2/adapters/unicorn" @@ -387,6 +388,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderTrafficGate: trafficgate.Builder, openrtb_ext.BidderTriplelift: triplelift.Builder, openrtb_ext.BidderTripleliftNative: triplelift_native.Builder, + openrtb_ext.BidderTrustedstack: trustedstack.Builder, openrtb_ext.BidderUcfunnel: ucfunnel.Builder, openrtb_ext.BidderUndertone: undertone.Builder, openrtb_ext.BidderUnicorn: unicorn.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index ea74cf94b8c..b9ffb659a37 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -197,6 +197,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderTrafficGate, BidderTriplelift, BidderTripleliftNative, + BidderTrustedstack, BidderUcfunnel, BidderUndertone, BidderUnicorn, @@ -481,6 +482,7 @@ const ( BidderTrafficGate BidderName = "trafficgate" BidderTriplelift BidderName = "triplelift" BidderTripleliftNative BidderName = "triplelift_native" + BidderTrustedstack BidderName = "trustedstack" BidderUcfunnel BidderName = "ucfunnel" BidderUndertone BidderName = "undertone" BidderUnicorn BidderName = "unicorn" diff --git a/openrtb_ext/imp_trustedstack.go b/openrtb_ext/imp_trustedstack.go new file mode 100644 index 00000000000..22914929689 --- /dev/null +++ b/openrtb_ext/imp_trustedstack.go @@ -0,0 +1,6 @@ +package openrtb_ext + +type ExtImpTrustedstack struct { + Cid string `json:"cid"` + Crid string `json:"crid"` +} diff --git a/static/bidder-info/trustedstack.yaml b/static/bidder-info/trustedstack.yaml new file mode 100644 index 00000000000..ffa48d261d4 --- /dev/null +++ b/static/bidder-info/trustedstack.yaml @@ -0,0 +1,24 @@ +endpoint: "https://prebid-adapter.trustedstack.com/rtb/pb/trustedstacks2s" +extra_info: "https://trustedstack.golang.pbs.com" +maintainer: + email: "product@trustedstack.com" +gvlVendorID: 1288 +endpointCompression: gzip +openrtb: + version: 2.6 +modifyingVastXmlAllowed: true +capabilities: + app: + mediaTypes: + - banner + - video + - native + site: + mediaTypes: + - banner + - video + - native +userSync: + redirect: + url: https://hb.trustedstack.com/cksync?cs=1&type=pbs&ovsid=setstatuscode&bidder=trustedstack&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}} + userMacro: "" \ No newline at end of file diff --git a/static/bidder-params/trustedstack.json b/static/bidder-params/trustedstack.json new file mode 100644 index 00000000000..b52e7bf3f7f --- /dev/null +++ b/static/bidder-params/trustedstack.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Trustedstack Adapter Params", + "description": "A schema which validates params accepted by the Trustedstack adapter", + "type": "object", + "properties": { + "cid": { + "type": "string", + "minLength": 1, + "description": "The customer id provided by Trustedstack." + }, + "crid": { + "type": "string", + "minLength": 1, + "description": "The placement id provided by Trustedstack." + } + }, + "required": [ + "cid", + "crid" + ] +} \ No newline at end of file