diff --git a/adapters/nexx360/nexx360.go b/adapters/nexx360/nexx360.go new file mode 100644 index 00000000000..f91961918ce --- /dev/null +++ b/adapters/nexx360/nexx360.go @@ -0,0 +1,226 @@ +package nexx360 + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + + "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" + "github.com/prebid/prebid-server/v3/version" +) + +type adapter struct { + endpoint string +} + +type Ext struct { + Nexx360 json.RawMessage `json:"nexx360"` +} + +type Nexx360Caller struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +type ReqExt struct { + Nexx360 *ReqNexx360Ext `json:"nexx360,omitempty"` +} + +type ReqNexx360Ext struct { + Caller []Nexx360Caller `json:"caller,omitempty"` +} + +type Nexx360ResBidExt struct { + BidType string `json:"bidType,omitempty"` +} + +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + return &adapter{endpoint: config.Endpoint}, nil +} + +// CALLER Info used to track Prebid Server +// as one of the hops in the request to exchange + +func getVersion() string { + if version.Ver != "" { + return version.Ver + } + return "n/a" +} + +var CALLER = Nexx360Caller{"Prebid-Server", getVersion()} + +func processImps(impList []openrtb2.Imp) (imp []openrtb2.Imp, tagId string, placement string, error error) { + var imps []openrtb2.Imp + for idx, imp := range impList { + var bidderExt adapters.ExtImpBidder + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { + return nil, "", "", &errortypes.BadInput{ + Message: err.Error(), + } + } + + impExt := Ext{ + Nexx360: bidderExt.Bidder, + } + + impExtJSON, err := json.Marshal(impExt) + if err != nil { + return nil, "", "", &errortypes.BadInput{ + Message: err.Error(), + } + } + + impCopy := imp + impCopy.Ext = impExtJSON + imps = append(imps, impCopy) + if idx == 0 { + var nexx360Ext openrtb_ext.ExtImpNexx360 + if err := jsonutil.Unmarshal(bidderExt.Bidder, &nexx360Ext); err != nil { + return nil, "", "", &errortypes.BadInput{ + Message: err.Error(), + } + } + tagId = nexx360Ext.TagId + placement = nexx360Ext.Placement + } + } + + return imps, tagId, placement, nil +} + +func makeReqExt() ([]byte, error) { + reqExt := ReqExt{ + Nexx360: &ReqNexx360Ext{ + Caller: []Nexx360Caller{CALLER}, + }, + } + + return json.Marshal(reqExt) +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var imp, tagId, placement, err = processImps(request.Imp) + if err != nil { + return nil, []error{err} + } + + request.Imp = imp + + urlBuilder, err := url.Parse(a.endpoint) + if err != nil { + return nil, []error{err} + } + + query := url.Values{} + + if placement != "" { + query.Add("placement", placement) + } + + if tagId != "" { + query.Add("tag_id", tagId) + } + urlBuilder.RawQuery = query.Encode() + + uri := urlBuilder.String() + + reqExt, err := makeReqExt() + if err != nil { + return nil, []error{err} + } + request.Ext = reqExt + + // Last Step + reqJSON, err := json.Marshal(request) + if err != nil { + return nil, []error{err} + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json") + + adapter := &adapters.RequestData{ + Method: http.MethodPost, + Uri: uri, + Body: reqJSON, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + } + + return []*adapters.RequestData{adapter}, nil +} + +// MakeBids make the bids for the bid response. +func (a *adapter) MakeBids(request *openrtb2.BidRequest, externalRequest *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{&errortypes.BadInput{ + Message: fmt.Sprintf("Unexpected http status code: %d", responseData.StatusCode), + }} + } + + var response openrtb2.BidResponse + + if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil { + return nil, []error{err} + } + + var Bids []*adapters.TypedBid + var errors []error + for _, seatBid := range response.SeatBid { + for i, bid := range seatBid.Bid { + + bidType, err := getBidType(bid) + if err != nil { + errors = append(errors, err) + continue + } + Bids = append(Bids, &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + }) + } + } + if len(Bids) == 0 { + return nil, nil + } + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(Bids)) + bidResponse.Bids = Bids + if response.Cur != "" { + bidResponse.Currency = response.Cur + } + + return bidResponse, errors +} + +func getBidType(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + var bidExt Nexx360ResBidExt + err := jsonutil.Unmarshal(bid.Ext, &bidExt) + if err == nil { + if bidExt.BidType == "video" { + return openrtb_ext.BidTypeVideo, nil + } + if bidExt.BidType == "audio" { + return openrtb_ext.BidTypeAudio, nil + } + if bidExt.BidType == "native" { + return openrtb_ext.BidTypeNative, nil + } + if bidExt.BidType == "banner" { + return openrtb_ext.BidTypeBanner, nil + } + } + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("unable to fetch mediaType in multi-format: %s", bid.ImpID), + } +} diff --git a/adapters/nexx360/nexx360_test.go b/adapters/nexx360/nexx360_test.go new file mode 100644 index 00000000000..f7a8741f176 --- /dev/null +++ b/adapters/nexx360/nexx360_test.go @@ -0,0 +1,20 @@ +package nexx360 + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderNexx360, config.Adapter{ + Endpoint: "http://fast.nexx360.io/prebid-server"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "nexx360test", bidder) +} diff --git a/adapters/nexx360/nexx360test/exemplary/simple-audio.json b/adapters/nexx360/nexx360test/exemplary/simple-audio.json new file mode 100644 index 00000000000..70997739ec7 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-audio.json @@ -0,0 +1,158 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "audio": { + "mimes": ["audio/mp3"], + "protocols": [2, 5], + "minduration": 10, + "maxduration": 30 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "audio": { + "mimes": ["audio/mp3"], + "protocols": [2, 5], + "minduration": 10, + "maxduration": 30 + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "ext": { + "mediaType": "audio", + "bidType": "audio", + "tagId": "testnexx", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "ext": { + "mediaType": "audio", + "bidType": "audio", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "audio" + } + ] + } + ] +} + diff --git a/adapters/nexx360/nexx360test/exemplary/simple-banner-cookie-uid.json b/adapters/nexx360/nexx360test/exemplary/simple-banner-cookie-uid.json new file mode 100755 index 00000000000..28a575d7a8f --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-banner-cookie-uid.json @@ -0,0 +1,146 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "buyeruid": "nexx360-use-id" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "buyeruid": "nexx360-use-id" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "test-ad", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "test-ad", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/exemplary/simple-banner-inapp.json b/adapters/nexx360/nexx360test/exemplary/simple-banner-inapp.json new file mode 100755 index 00000000000..0b65b325855 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-banner-inapp.json @@ -0,0 +1,139 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "test.app.bundle" + }, + "device": { + "ifa": "test-ifa-123456", + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "app": { + "bundle": "test.app.bundle" + }, + "device": { + "ifa": "test-ifa-123456", + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "

test ad

", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "

test ad

", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/exemplary/simple-banner-multiple-bids.json b/adapters/nexx360/nexx360test/exemplary/simple-banner-multiple-bids.json new file mode 100644 index 00000000000..d6354acde5b --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-banner-multiple-bids.json @@ -0,0 +1,237 @@ +{ + "mockBidRequest": { + "id": "test-request-id-multiple-bids", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "tagId": "testnex1" + } + } + }, + { + "id": "test-imp-id2", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "tagId": "testnex2" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnex1", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id-multiple-bids", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nexx360": { + "tagId": "testnex1" + } + } + }, + { + "id": "test-imp-id2", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nexx360": { + "tagId": "testnex2" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "test-imp-id", + "test-imp-id2" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "
Test Ad
", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnex1", + "ssp": "test" + } + } + ] + }, + { + "bid": [ + { + "id": "test-slot-id2", + "impid": "test-imp-id2", + "price": 0.5, + "crid": "creative-123", + "adm": "
Test Ad
", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnex2", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "
Test Ad
", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnex1", + "ssp": "test" + } + }, + "type": "banner" + }, + { + "bid": { + "id": "test-slot-id2", + "impid": "test-imp-id2", + "price": 0.5, + "crid": "creative-123", + "adm": "
Test Ad
", + "w": 300, + "h": 250, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnex2", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/exemplary/simple-banner-placement-tagid.json b/adapters/nexx360/nexx360test/exemplary/simple-banner-placement-tagid.json new file mode 100644 index 00000000000..1866265c49f --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-banner-placement-tagid.json @@ -0,0 +1,112 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "bidder": { + "tagId": "testnexx", + "placement": "test" + + } + } + } + ], + "site": {} + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?placement=test&tag_id=testnexx", + "body": { + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "nexx360": { + "placement": "test", + "tagId": "testnexx" + } + } + } + ], + "site": {} + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "testalias", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-banner", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-banner", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/nexx360/nexx360test/exemplary/simple-banner-placement.json b/adapters/nexx360/nexx360test/exemplary/simple-banner-placement.json new file mode 100644 index 00000000000..01d93798c60 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-banner-placement.json @@ -0,0 +1,110 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "bidder": { + "placement": "test" + + } + } + } + ], + "site": {} + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?placement=test", + "body": { + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "nexx360": { + "placement": "test" + } + } + } + ], + "site": {} + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "testalias", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-banner", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-banner", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/nexx360/nexx360test/exemplary/simple-banner.json b/adapters/nexx360/nexx360test/exemplary/simple-banner.json new file mode 100644 index 00000000000..b8e7ba9f000 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-banner.json @@ -0,0 +1,114 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + + } + } + } + ], + "site": {}, + "ext": { + "nexx360": "Prebid-Server", + "test": 1 + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "site": {} + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "testalias", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-banner", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-banner", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/nexx360/nexx360test/exemplary/simple-multi-type-banner.json b/adapters/nexx360/nexx360test/exemplary/simple-multi-type-banner.json new file mode 100644 index 00000000000..ecc72dee184 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-multi-type-banner.json @@ -0,0 +1,178 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 300, + "h": 250 + }, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 300, + "h": 250 + }, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "

test ad

", + "h": 250, + "w": 300, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "

test ad

", + "h": 250, + "w": 300, + "ext": { + "mediaType": "banner", + "bidType": "banner", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "banner" + } + ] + } + ] +} + diff --git a/adapters/nexx360/nexx360test/exemplary/simple-multi-type-video.json b/adapters/nexx360/nexx360test/exemplary/simple-multi-type-video.json new file mode 100644 index 00000000000..754b3538dc7 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-multi-type-video.json @@ -0,0 +1,178 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 300, + "h": 250 + }, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 300, + "h": 250 + }, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "h": 250, + "w": 300, + "ext": { + "mediaType": "video", + "bidType": "video", + "tagId": "testnexx", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "h": 250, + "w": 300, + "ext": { + "mediaType": "video", + "bidType": "video", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "video" + } + ] + } + ] +} + diff --git a/adapters/nexx360/nexx360test/exemplary/simple-native.json b/adapters/nexx360/nexx360test/exemplary/simple-native.json new file mode 100644 index 00000000000..1f0b9edcb2d --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-native.json @@ -0,0 +1,120 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "test-imp-id", + "native": { + "ver": "1.2", + "request": "{\"ver\":\"1.2\",\"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": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [ + { + "id": "test-imp-id", + "native": { + "ver": "1.2", + "request": "{\"ver\":\"1.2\",\"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": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "grid", + "bid": [ + { + "id": "randomid", + "impid": "test-imp-id", + "price": 0.5, + "adid": "12345678", + "adm": "{\"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": { + "mediaType": "native", + "bidType": "native", + "tagId": "testnexx", + "ssp": "test" + }, + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 0.5, + "adm": "{\"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}}]}", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "w": 300, + "h": 250, + "ext": { + "mediaType": "native", + "bidType": "native", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "native" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/exemplary/simple-video.json b/adapters/nexx360/nexx360test/exemplary/simple-video.json new file mode 100644 index 00000000000..68ce33402d2 --- /dev/null +++ b/adapters/nexx360/nexx360test/exemplary/simple-video.json @@ -0,0 +1,162 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "criteo.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "criteo-eid" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 300, + "h": 250 + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "h": 250, + "w": 300, + "ext": { + "mediaType": "video", + "bidType": "video", + "tagId": "testnexx", + "ssp": "test" + } + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "h": 250, + "w": 300, + "ext": { + "mediaType": "video", + "bidType": "video", + "tagId": "testnexx", + "ssp": "test" + } + }, + "type": "video" + } + ] + } + ] +} + diff --git a/adapters/nexx360/nexx360test/supplemental/204-response.json b/adapters/nexx360/nexx360test/supplemental/204-response.json new file mode 100644 index 00000000000..6a9cc7e5dac --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/204-response.json @@ -0,0 +1,121 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "imp": [ + { + "id": "some-impression-id", + "tagid": "ogTAGID", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480, + "minduration": 120, + "maxduration": 150 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id", + "video": { + "mimes": [ + "video/mp4" + ], + "minduration": 120, + "maxduration": 150, + "w": 640, + "h": 480 + }, + "tagid": "ogTAGID", + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000, + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "some-impression-id" + ] + }, + "mockResponse": { + "status": 204 + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/supplemental/400-response.json b/adapters/nexx360/nexx360test/supplemental/400-response.json new file mode 100644 index 00000000000..e430851e884 --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/400-response.json @@ -0,0 +1,127 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "imp": [ + { + "id": "some-impression-id", + "tagid": "ogTAGID", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480, + "minduration": 120, + "maxduration": 150 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id", + "video": { + "mimes": [ + "video/mp4" + ], + "minduration": 120, + "maxduration": 150, + "w": 640, + "h": 480 + }, + "tagid": "ogTAGID", + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000, + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "some-impression-id" + ] + }, + "mockResponse": { + "status": 400 + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected http status code: 400", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/supplemental/500-response.json b/adapters/nexx360/nexx360test/supplemental/500-response.json new file mode 100644 index 00000000000..4a06526ee16 --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/500-response.json @@ -0,0 +1,127 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "imp": [ + { + "id": "some-impression-id", + "tagid": "ogTAGID", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480, + "minduration": 120, + "maxduration": 150 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id", + "video": { + "mimes": [ + "video/mp4" + ], + "minduration": 120, + "maxduration": 150, + "w": 640, + "h": 480 + }, + "tagid": "ogTAGID", + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000, + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "some-impression-id" + ] + }, + "mockResponse": { + "status": 500 + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected http status code: 500", + "comparison": "literal" + } + ] +} diff --git a/adapters/nexx360/nexx360test/supplemental/empty_seatbid.json b/adapters/nexx360/nexx360test/supplemental/empty_seatbid.json new file mode 100644 index 00000000000..1abf64d3e58 --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/empty_seatbid.json @@ -0,0 +1,125 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "imp": [ + { + "id": "some-impression-id", + "tagid": "ogTAGID", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480, + "minduration": 120, + "maxduration": 150 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id", + "video": { + "mimes": [ + "video/mp4" + ], + "minduration": 120, + "maxduration": 150, + "w": 640, + "h": 480 + }, + "tagid": "ogTAGID", + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user" + }, + "tmax": 1000, + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + } + }, + "impIDs": [ + "some-impression-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [] + } + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/supplemental/ext.json b/adapters/nexx360/nexx360test/supplemental/ext.json new file mode 100644 index 00000000000..68584236617 --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/ext.json @@ -0,0 +1,33 @@ +{ + "mockBidRequest": { + "id": "testid", + "imp": [ + { + "id": "testimpid", + "banner": { + "format": [ + { + "w": 320, + "h": 250 + }, + { + "w": 320, + "h": 300 + } + ], + "w": 320, + "h": 250 + }, + "ext": { + "placement_id": "1265" + } + } + ] + }, + "expectedMakeRequestsErrors": [ + { + "value": "expect { or n, but found", + "comparison": "startswith" + } + ] +} diff --git a/adapters/nexx360/nexx360test/supplemental/invalid-bid-response.json b/adapters/nexx360/nexx360test/supplemental/invalid-bid-response.json new file mode 100644 index 00000000000..b3b45b21128 --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/invalid-bid-response.json @@ -0,0 +1,77 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + } + } + } + ], + "site": {}, + "ext": { + "nexx360": "Prebid-Server", + "test": 1 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "site": {} + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": {}, + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "cannot unmarshal openrtb2.BidResponse.SeatBid: decode slice: expect [ or n, but found {", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/nexx360/nexx360test/supplemental/wrong-payload.json b/adapters/nexx360/nexx360test/supplemental/wrong-payload.json new file mode 100644 index 00000000000..bbcf590683c --- /dev/null +++ b/adapters/nexx360/nexx360test/supplemental/wrong-payload.json @@ -0,0 +1,82 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "bidder": { + "tagId": "testnexx" + + } + } + } + ], + "site": {} + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fast.nexx360.io/prebid-server?tag_id=testnexx", + "body": { + "ext": { + "nexx360": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "w": 728, + "h": 90 + }, + "ext": { + "nexx360": { + "tagId": "testnexx" + } + } + } + ], + "site": {} + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "testalias", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-banner", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + } + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/nexx360/params_test.go b/adapters/nexx360/params_test.go new file mode 100644 index 00000000000..dc21d211347 --- /dev/null +++ b/adapters/nexx360/params_test.go @@ -0,0 +1,55 @@ +package nexx360 + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +// This file actually intends to test static/bidder-params/nexx360.json +// +// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.nexx360 + +// TestValidParams makes sure that the Nexx360 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.BidderNexx360, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected Nexx360 params: %s", validParam) + } + } +} + +// TestInvalidParams makes sure that the Nexx360 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.BidderNexx360, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"tagId": "testnexx"}`, + `{"placement": "testnexx"}`, + `{"tagId": "testnexx", "placement": "testnexx"}`, +} + +var invalidParams = []string{ + `{"productId": "inview"}`, + `{"tagId": "" }`, + `{"placement": "" }`, + `{"tagId": "testnexx", "placement": "" }`, + `{"tagId": "", "placement": "testnexx"}`, + `{}`, +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 7647de71786..7b36388ad54 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -156,6 +156,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/motorik" "github.com/prebid/prebid-server/v3/adapters/nativo" "github.com/prebid/prebid-server/v3/adapters/nextmillennium" + "github.com/prebid/prebid-server/v3/adapters/nexx360" "github.com/prebid/prebid-server/v3/adapters/nobid" "github.com/prebid/prebid-server/v3/adapters/ogury" "github.com/prebid/prebid-server/v3/adapters/oms" @@ -406,6 +407,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderMotorik: motorik.Builder, openrtb_ext.BidderNativo: nativo.Builder, openrtb_ext.BidderNextMillennium: nextmillennium.Builder, + openrtb_ext.BidderNexx360: nexx360.Builder, openrtb_ext.BidderNoBid: nobid.Builder, openrtb_ext.BidderOgury: ogury.Builder, openrtb_ext.BidderOms: oms.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 10755dfd7fd..71f6790a395 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -174,6 +174,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderMotorik, BidderNativo, BidderNextMillennium, + BidderNexx360, BidderNoBid, BidderOgury, BidderOms, @@ -528,6 +529,7 @@ const ( BidderMotorik BidderName = "motorik" BidderNativo BidderName = "nativo" BidderNextMillennium BidderName = "nextmillennium" + BidderNexx360 BidderName = "nexx360" BidderNoBid BidderName = "nobid" BidderOgury BidderName = "ogury" BidderOms BidderName = "oms" diff --git a/openrtb_ext/imp_nexx360.go b/openrtb_ext/imp_nexx360.go new file mode 100644 index 00000000000..29297aece2c --- /dev/null +++ b/openrtb_ext/imp_nexx360.go @@ -0,0 +1,7 @@ +package openrtb_ext + +// ExtNexx360 defines the contract for bidrequest.imp[i].ext.prebid.bidder.nexx360 +type ExtImpNexx360 struct { + TagId string `json:"tagId,omitempty"` + Placement string `json:"placement,omitempty"` // Placement ID +} diff --git a/static/bidder-info/1accord.yaml b/static/bidder-info/1accord.yaml new file mode 100644 index 00000000000..4a6b8199be9 --- /dev/null +++ b/static/bidder-info/1accord.yaml @@ -0,0 +1 @@ +aliasOf: "nexx360" diff --git a/static/bidder-info/easybid.yaml b/static/bidder-info/easybid.yaml new file mode 100644 index 00000000000..4a6b8199be9 --- /dev/null +++ b/static/bidder-info/easybid.yaml @@ -0,0 +1 @@ +aliasOf: "nexx360" diff --git a/static/bidder-info/nexx360.yaml b/static/bidder-info/nexx360.yaml new file mode 100644 index 00000000000..0a0b186ec91 --- /dev/null +++ b/static/bidder-info/nexx360.yaml @@ -0,0 +1,19 @@ +endpoint: "http://fast.nexx360.io/prebid-server" +maintainer: + email: "tech@nexx360.io" +endpointCompression: gzip +geoscope: + - global +capabilities: + app: + mediaTypes: + - banner + - video + - native + - audio + site: + mediaTypes: + - banner + - video + - native + - audio diff --git a/static/bidder-info/prismassp.yaml b/static/bidder-info/prismassp.yaml new file mode 100644 index 00000000000..4a6b8199be9 --- /dev/null +++ b/static/bidder-info/prismassp.yaml @@ -0,0 +1 @@ +aliasOf: "nexx360" diff --git a/static/bidder-params/nexx360.json b/static/bidder-params/nexx360.json new file mode 100644 index 00000000000..a2f35276ace --- /dev/null +++ b/static/bidder-params/nexx360.json @@ -0,0 +1,32 @@ + +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Nexx360 Adapter Params", + "description": "A schema which validates params accepted by the Nexx360 adapter", + + "type": "object", + "properties": { + "tagId": { + "type": "string", + "minLength": 1, + "description": "TagId" + }, + "placement": { + "type": "string", + "minLength": 1, + "description": "Placement" + } + }, + "anyOf": [ + { + "required": [ + "tagId" + ] + }, + { + "required": [ + "placement" + ] + } + ] + } \ No newline at end of file