diff --git a/adapters/tpmn/params_test.go b/adapters/tpmn/params_test.go new file mode 100644 index 00000000000..7bd7c478638 --- /dev/null +++ b/adapters/tpmn/params_test.go @@ -0,0 +1,44 @@ +package tpmn + +import ( + "encoding/json" + "github.com/prebid/prebid-server/openrtb_ext" + "testing" +) + +var validParams = []string{ + `{"inventoryId": 10000001}`, +} + +var invalidParams = []string{ + `{"inventoryId": "00000001"}`, + `{"inventoryid": 100000000}`, +} + +// TestValidParams makes sure that the tpmn schema accepts all imp.ext fields which we intend to support. +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.BidderTpmn, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected TPMN params: %s", validParam) + } + } +} + +// TestInvalidParams makes sure that the tpmn schema rejects all the imp.ext fields we don't support. +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.BidderTpmn, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} diff --git a/adapters/tpmn/tpmn.go b/adapters/tpmn/tpmn.go new file mode 100644 index 00000000000..7afe94e5f79 --- /dev/null +++ b/adapters/tpmn/tpmn.go @@ -0,0 +1,126 @@ +package tpmn + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/prebid/openrtb/v19/openrtb2" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/config" + "github.com/prebid/prebid-server/openrtb_ext" +) + +// TpmnAdapter struct +type adapter struct { + uri string +} + +// MakeRequests makes the HTTP requests which should be made to fetch bids from TpmnBidder. +func (rcv *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + validImps, errs := getValidImpressions(request, reqInfo) + if len(validImps) == 0 { + return nil, errs + } + + request.Imp = validImps + + requestBodyJSON, 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") + headers.Add("Accept", "application/json") + + return []*adapters.RequestData{{ + Method: http.MethodPost, + Uri: rcv.uri, + Body: requestBodyJSON, + Headers: headers, + }}, errs +} + +// getValidImpressions validate imps and check for bid floor currency. Convert to EUR if necessary +func getValidImpressions(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]openrtb2.Imp, []error) { + var errs []error + var validImps []openrtb2.Imp + + for _, imp := range request.Imp { + if err := preprocessBidFloorCurrency(&imp, reqInfo); err != nil { + errs = append(errs, err) + continue + } + validImps = append(validImps, imp) + } + return validImps, errs +} + +func preprocessBidFloorCurrency(imp *openrtb2.Imp, reqInfo *adapters.ExtraRequestInfo) error { + // we expect every currency related data to be EUR + if imp.BidFloor > 0 && strings.ToUpper(imp.BidFloorCur) != "USD" && imp.BidFloorCur != "" { + if convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD"); err != nil { + return err + } else { + imp.BidFloor = convertedValue + } + } + imp.BidFloorCur = "USD" + return nil +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if adapters.IsResponseStatusCodeNoContent(responseData) { + return nil, nil + } + + if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { + return nil, []error{err} + } + + var response openrtb2.BidResponse + if err := json.Unmarshal(responseData.Body, &response); err != nil { + return nil, []error{fmt.Errorf("bid response unmarshal: %v", err)} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + bidResponse.Currency = response.Cur + for _, seatBid := range response.SeatBid { + for i, bid := range seatBid.Bid { + bidType, err := getMediaTypeForImp(bid) + if err != nil { + return nil, []error{err} + } + b := &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + } + bidResponse.Bids = append(bidResponse.Bids, b) + } + } + return bidResponse, nil +} + +func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + switch bid.MType { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner, nil + case openrtb2.MarkupVideo: + return openrtb_ext.BidTypeVideo, nil + case openrtb2.MarkupNative: + return openrtb_ext.BidTypeNative, nil + default: + return "", fmt.Errorf("unsupported MType %d", bid.MType) + } +} + +// Builder builds a new instance of the TpmnBidder adapter for the given bidder with the given config. +func Builder(_ openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + bidder := &adapter{ + uri: config.Endpoint, + } + return bidder, nil +} diff --git a/adapters/tpmn/tpmn_test.go b/adapters/tpmn/tpmn_test.go new file mode 100644 index 00000000000..6fbd85936f1 --- /dev/null +++ b/adapters/tpmn/tpmn_test.go @@ -0,0 +1,20 @@ +package tpmn + +import ( + "testing" + + "github.com/prebid/prebid-server/adapters/adapterstest" + "github.com/prebid/prebid-server/config" + "github.com/prebid/prebid-server/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderTpmn, config.Adapter{ + Endpoint: "https://gat.tpmn.io/ortb/pbs_bidder"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "tpmntest", bidder) +} diff --git a/adapters/tpmn/tpmntest/exemplary/simple-banner.json b/adapters/tpmn/tpmntest/exemplary/simple-banner.json new file mode 100644 index 00000000000..197d03b174e --- /dev/null +++ b/adapters/tpmn/tpmntest/exemplary/simple-banner.json @@ -0,0 +1,135 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "00000001", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "00000001", + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "tpmn" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/tpmn/tpmntest/exemplary/simple-native.json b/adapters/tpmn/tpmntest/exemplary/simple-native.json new file mode 100644 index 00000000000..1880c74ac7e --- /dev/null +++ b/adapters/tpmn/tpmntest/exemplary/simple-native.json @@ -0,0 +1,119 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "native": { + "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "native": { + "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}", + "ver": "1.1" + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "mtype": 4, + "ext": { + "prebid": { + "type": "native" + } + } + } + ], + "seat": "tpmn" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "mtype": 4, + "ext": { + "prebid": { + "type": "native" + } + } + }, + "type": "native" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/tpmn/tpmntest/exemplary/simple-site-banner.json b/adapters/tpmn/tpmntest/exemplary/simple-site-banner.json new file mode 100644 index 00000000000..8f7c5d59301 --- /dev/null +++ b/adapters/tpmn/tpmntest/exemplary/simple-site-banner.json @@ -0,0 +1,132 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "site": { + "id": "1", + "domain": "test.com" + }, + "device": { + "ip": "123.123.123.123" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "site": { + "id": "1", + "domain": "test.com" + }, + "device": { + "ip": "123.123.123.123" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 468, + "h": 60, + "mtype": 1, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "tpmn" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 468, + "h": 60, + "mtype": 1, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} + \ No newline at end of file diff --git a/adapters/tpmn/tpmntest/exemplary/simple-site-native.json b/adapters/tpmn/tpmntest/exemplary/simple-site-native.json new file mode 100644 index 00000000000..20e6c23e966 --- /dev/null +++ b/adapters/tpmn/tpmntest/exemplary/simple-site-native.json @@ -0,0 +1,104 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "device": { + "ip":"123.123.123.123" + }, + "imp": [ + { + "id": "test-imp-id", + "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\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":60,\"hmin\":60,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":75}},{\"id\":4,\"required\":0,\"data\":{\"type\":6,\"len\":1000}},{\"id\":5,\"required\":0,\"data\":{\"type\":7,\"len\":1000}},{\"id\":6,\"required\":0,\"data\":{\"type\":11,\"len\":1000}}]}" + }, + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "device": { + "ip":"123.123.123.123" + }, + "imp": [ + { + "id": "test-imp-id", + "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\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":60,\"hmin\":60,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":75}},{\"id\":4,\"required\":0,\"data\":{\"type\":6,\"len\":1000}},{\"id\":5,\"required\":0,\"data\":{\"type\":7,\"len\":1000}},{\"id\":6,\"required\":0,\"data\":{\"type\":11,\"len\":1000}}]}" + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "tpmn", + "bid": [{ + "id": "1", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-adm", + "crid": "test-crid", + "mtype": 4 + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "1", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-adm", + "crid": "test-crid", + "mtype": 4 + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/tpmn/tpmntest/exemplary/simple-site-video.json b/adapters/tpmn/tpmntest/exemplary/simple-site-video.json new file mode 100644 index 00000000000..7b2375cd07a --- /dev/null +++ b/adapters/tpmn/tpmntest/exemplary/simple-site-video.json @@ -0,0 +1,128 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "device": { + "ip":"123.123.123.123" + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 3, + 5, + 6 + ], + "w": 1024, + "h": 576 + }, + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "device": { + "ip":"123.123.123.123" + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 3, + 5, + 6 + ], + "w": 1024, + "h": 576 + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "seat": "tpmn", + "bid": [ + { + "id": "1", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-adm", + "crid": "test-crid", + "w": 1024, + "h": 576, + "mtype": 2 + } + ] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "1", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-adm", + "crid": "test-crid", + "w": 1024, + "h": 576, + "mtype": 2 + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/tpmn/tpmntest/exemplary/simple-video.json b/adapters/tpmn/tpmntest/exemplary/simple-video.json new file mode 100644 index 00000000000..505b6167069 --- /dev/null +++ b/adapters/tpmn/tpmntest/exemplary/simple-video.json @@ -0,0 +1,130 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 1024, + "h": 576 + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 1024, + "h": 576 + }, + + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "00:01:00", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "mtype": 2, + "ext": { + "prebid": { + "type": "video" + } + } + } + ], + "seat": "tpmn" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "00:01:00", + "cid": "test_cid", + "crid": "test_crid", + "mtype": 2, + "dealid": "test_dealid", + "ext": { + "prebid": { + "type": "video" + } + } + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/tpmn/tpmntest/supplemental/bad-imp-ext.json b/adapters/tpmn/tpmntest/supplemental/bad-imp-ext.json new file mode 100644 index 00000000000..3bbb23f95a4 --- /dev/null +++ b/adapters/tpmn/tpmntest/supplemental/bad-imp-ext.json @@ -0,0 +1,79 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "00000001", + "ext": { + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "00000001", + "bidfloorcur": "USD", + "ext": { + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + } + } + }, + "mockResponse": { + "status": 204, + "body": { + } + } + } + ], + "expectedBidResponses": [ + ] +} diff --git a/adapters/tpmn/tpmntest/supplemental/bad_response.json b/adapters/tpmn/tpmntest/supplemental/bad_response.json new file mode 100644 index 00000000000..12c3a72d49f --- /dev/null +++ b/adapters/tpmn/tpmntest/supplemental/bad_response.json @@ -0,0 +1,87 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 200, + "body": "" + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "bid response unmarshal: json: cannot unmarshal string into Go value of type openrtb2.BidResponse", + "comparison": "literal" + } + ] +} diff --git a/adapters/tpmn/tpmntest/supplemental/no-imp-ext.json b/adapters/tpmn/tpmntest/supplemental/no-imp-ext.json new file mode 100644 index 00000000000..8bcbb93d004 --- /dev/null +++ b/adapters/tpmn/tpmntest/supplemental/no-imp-ext.json @@ -0,0 +1,81 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "16", + "ext": "" + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "16", + "ext": "", + "bidfloorcur": "USD" + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx" + } + } + }, + "mockResponse": { + "status": 200, + "body": "" + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "bid response unmarshal: json: cannot unmarshal string into Go value of type openrtb2.BidResponse", + "comparison": "literal" + } + ] +} + \ No newline at end of file diff --git a/adapters/tpmn/tpmntest/supplemental/status-204.json b/adapters/tpmn/tpmntest/supplemental/status-204.json new file mode 100644 index 00000000000..fdcd3f7fd55 --- /dev/null +++ b/adapters/tpmn/tpmntest/supplemental/status-204.json @@ -0,0 +1,81 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/tpmn/tpmntest/supplemental/status-404.json b/adapters/tpmn/tpmntest/supplemental/status-404.json new file mode 100644 index 00000000000..74ced15217c --- /dev/null +++ b/adapters/tpmn/tpmntest/supplemental/status-404.json @@ -0,0 +1,86 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://gat.tpmn.io/ortb/pbs_bidder", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "bidfloorcur": "USD", + "ext": { + "bidder": { + "inventoryId": 10000001 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 404, + "body": {} + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 404. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index a1038d7152d..11529c5e9c3 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -157,6 +157,7 @@ import ( "github.com/prebid/prebid-server/adapters/taboola" "github.com/prebid/prebid-server/adapters/tappx" "github.com/prebid/prebid-server/adapters/telaria" + "github.com/prebid/prebid-server/adapters/tpmn" "github.com/prebid/prebid-server/adapters/trafficgate" "github.com/prebid/prebid-server/adapters/triplelift" "github.com/prebid/prebid-server/adapters/triplelift_native" @@ -355,6 +356,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderTaboola: taboola.Builder, openrtb_ext.BidderTappx: tappx.Builder, openrtb_ext.BidderTelaria: telaria.Builder, + openrtb_ext.BidderTpmn: tpmn.Builder, openrtb_ext.BidderTrafficGate: trafficgate.Builder, openrtb_ext.BidderTriplelift: triplelift.Builder, openrtb_ext.BidderTripleliftNative: triplelift_native.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index e9cc81f8c38..c873e9ab567 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -254,6 +254,7 @@ const ( BidderTaboola BidderName = "taboola" BidderTappx BidderName = "tappx" BidderTelaria BidderName = "telaria" + BidderTpmn BidderName = "tpmn" BidderTrafficGate BidderName = "trafficgate" BidderTriplelift BidderName = "triplelift" BidderTripleliftNative BidderName = "triplelift_native" @@ -454,6 +455,7 @@ func CoreBidderNames() []BidderName { BidderTaboola, BidderTappx, BidderTelaria, + BidderTpmn, BidderTrafficGate, BidderTriplelift, BidderTripleliftNative, diff --git a/openrtb_ext/imp_tpmn.go b/openrtb_ext/imp_tpmn.go new file mode 100644 index 00000000000..373b3089cc8 --- /dev/null +++ b/openrtb_ext/imp_tpmn.go @@ -0,0 +1,6 @@ +package openrtb_ext + +// ExtImpTpmn defines TPMN specifiec param +type ExtImpTpmn struct { + InventoryId int `json:"inventoryId"` +} diff --git a/static/bidder-info/tpmn.yaml b/static/bidder-info/tpmn.yaml new file mode 100644 index 00000000000..8d88c451da6 --- /dev/null +++ b/static/bidder-info/tpmn.yaml @@ -0,0 +1,20 @@ +endpoint: "https://gat.tpmn.io/ortb/pbs_bidder" +maintainer: + email: "prebid@tpmn.io" +modifyingVastXmlAllowed: true +endpointCompression: GZIP +capabilities: + app: + mediaTypes: + - banner + - video + - native + site: + mediaTypes: + - banner + - video + - native +userSync: + redirect: + url: "https://gat.tpmn.io/sync/redirect?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}" + userMacro: "$UID" \ No newline at end of file diff --git a/static/bidder-params/tpmn.json b/static/bidder-params/tpmn.json new file mode 100644 index 00000000000..68b54373179 --- /dev/null +++ b/static/bidder-params/tpmn.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "TPMN Adapter Params", + "description": "A schema which validates params accepted by the TPMN adapter", + "type": "object", + "properties": { + "inventoryId": { + "description": "Inventory ID", + "type": "integer", + "minLength": 1 + } + }, + "required": [ + "inventoryId" + ] +} \ No newline at end of file