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