diff --git a/adapters/madsense/madsense.go b/adapters/madsense/madsense.go
new file mode 100644
index 00000000000..f5d0fa9df5c
--- /dev/null
+++ b/adapters/madsense/madsense.go
@@ -0,0 +1,126 @@
+package madsense
+
+import (
+ "encoding/json"
+ "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"
+)
+
+type adapter struct {
+ endpoint string
+}
+
+// Builder builds a new instance of the MadSense adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+ bidder := &adapter{
+ endpoint: config.Endpoint,
+ }
+ return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+ reqs := make([]*adapters.RequestData, 0, len(request.Imp))
+ var errs []error
+
+ appendReq := func(imps []openrtb2.Imp) {
+ req, err := a.makeRequest(request, imps)
+ if err != nil {
+ errs = append(errs, err)
+ return
+ }
+ if req != nil {
+ reqs = append(reqs, req)
+ }
+ }
+
+ var videoImps, bannerImps []openrtb2.Imp
+ for _, imp := range request.Imp {
+ if imp.Banner != nil {
+ bannerImps = append(bannerImps, imp)
+ } else if imp.Video != nil {
+ videoImps = append(videoImps, imp)
+ }
+ }
+
+ // we support video podding, so we want to send all video impressions in a single request
+ appendReq(videoImps)
+ for _, bannerImp := range bannerImps {
+ appendReq([]openrtb2.Imp{bannerImp})
+ }
+
+ return reqs, errs
+}
+
+func (a *adapter) makeRequest(request *openrtb2.BidRequest, imps []openrtb2.Imp) (*adapters.RequestData, error) {
+ if len(imps) == 0 {
+ return nil, nil
+ }
+ ext, err := parseImpExt(&imps[0])
+ if err != nil {
+ return nil, err
+ }
+
+ request.Imp = imps
+ body, err := json.Marshal(request)
+ if err != nil {
+ return nil, err
+ }
+
+ if request.Test == 1 {
+ ext.CompanyId = "test"
+ }
+
+ return &adapters.RequestData{
+ Method: http.MethodPost,
+ Uri: a.getEndpointURL(ext),
+ Body: body,
+ Headers: getHeaders(request),
+ ImpIDs: openrtb_ext.GetImpIDs(request.Imp),
+ }, nil
+}
+
+func (a *adapter) getEndpointURL(ext *openrtb_ext.ExtImpMadSense) string {
+ params := url.Values{}
+ params.Add("company_id", ext.CompanyId)
+ return a.endpoint + "?" + params.Encode()
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+ if adapters.IsResponseStatusCodeNoContent(response) {
+ return nil, nil
+ }
+
+ if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil {
+ return nil, []error{err}
+ }
+
+ var resp openrtb2.BidResponse
+ if err := jsonutil.Unmarshal(response.Body, &resp); err != nil {
+ return nil, []error{&errortypes.BadServerResponse{
+ Message: "Bad Server Response",
+ }}
+ }
+
+ var bidErrors []error
+ bidderResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+ for _, seatBid := range resp.SeatBid {
+ for i := range seatBid.Bid {
+ bid := &seatBid.Bid[i]
+ typedBid, err := getTypedBidFromBid(bid)
+ if err != nil {
+ bidErrors = append(bidErrors, err)
+ continue
+ }
+ bidderResponse.Bids = append(bidderResponse.Bids, typedBid)
+ }
+ }
+
+ return bidderResponse, bidErrors
+}
diff --git a/adapters/madsense/madsense_test.go b/adapters/madsense/madsense_test.go
new file mode 100644
index 00000000000..c9792e13921
--- /dev/null
+++ b/adapters/madsense/madsense_test.go
@@ -0,0 +1,18 @@
+package madsense
+
+import (
+ "github.com/prebid/prebid-server/v3/adapters/adapterstest"
+ "github.com/prebid/prebid-server/v3/config"
+ "github.com/prebid/prebid-server/v3/openrtb_ext"
+ "testing"
+)
+
+func TestJsonSamples(t *testing.T) {
+ bidder, buildErr := Builder(openrtb_ext.BidderMadSense, config.Adapter{
+ Endpoint: "https://test.localhost.com"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+ if buildErr != nil {
+ t.Fatalf("Builder returned unexpected error %v", buildErr)
+ }
+ adapterstest.RunJSONBidderTest(t, "madsensetest", bidder)
+}
diff --git a/adapters/madsense/madsensetest/exemplary/banner-app.json b/adapters/madsense/madsensetest/exemplary/banner-app.json
new file mode 100644
index 00000000000..bc1b2668fce
--- /dev/null
+++ b/adapters/madsense/madsensetest/exemplary/banner-app.json
@@ -0,0 +1,116 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ua": "user-agent",
+ "ip": "1.2.3.4"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ua": "user-agent",
+ "ip": "1.2.3.4"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0",
+ "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547",
+ "price": 10,
+ "impid": "test-imp-id",
+ "adm": "
",
+ "mtype": 1
+ }
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0",
+ "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547",
+ "price": 10,
+ "impid": "test-imp-id",
+ "adm": "
",
+ "mtype": 1
+ },
+ "type": "banner"
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+}
diff --git a/adapters/madsense/madsensetest/exemplary/banner-web.json b/adapters/madsense/madsensetest/exemplary/banner-web.json
new file mode 100644
index 00000000000..0ad9c5c8960
--- /dev/null
+++ b/adapters/madsense/madsensetest/exemplary/banner-web.json
@@ -0,0 +1,126 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ua": "user-agent",
+ "ipv6": "2001:db8:3333:4444:5555:6666:7777:8888"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page",
+ "ref": "https://example.com/page"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "Origin": [
+ "domain.com"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "2001:db8:3333:4444:5555:6666:7777:8888"
+ ],
+ "Referer": [
+ "https://example.com/page"
+ ]
+ },
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ua": "user-agent",
+ "ipv6": "2001:db8:3333:4444:5555:6666:7777:8888"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page",
+ "ref": "https://example.com/page"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0",
+ "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547",
+ "price": 10,
+ "impid": "test-imp-id",
+ "adm": "",
+ "mtype": 1
+ }
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0",
+ "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547",
+ "price": 10,
+ "impid": "test-imp-id",
+ "adm": "",
+ "mtype": 1
+ },
+ "type": "banner"
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+}
diff --git a/adapters/madsense/madsensetest/exemplary/mixed-imp-types.json b/adapters/madsense/madsensetest/exemplary/mixed-imp-types.json
new file mode 100644
index 00000000000..a453fd989ad
--- /dev/null
+++ b/adapters/madsense/madsensetest/exemplary/mixed-imp-types.json
@@ -0,0 +1,312 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ },
+ {
+ "id": "test-imp-id-2",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ },
+ {
+ "id": "test-imp-id-3",
+ "banner": {
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "Origin": [
+ "domain.com"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ },
+ {
+ "id": "test-imp-id-2",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ }
+ },
+ "impIDs":["test-imp-id","test-imp-id-2"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801",
+ "impid": "test-imp-id-2",
+ "price": 10,
+ "adm": "some-test-ad-2",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 30,
+ "cat": [
+ "IAB1-1"
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "Origin": [
+ "domain.com"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id-3",
+ "banner": {
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ }
+ },
+ "impIDs":["test-imp-id-3"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e2",
+ "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547",
+ "price": 10,
+ "impid": "test-imp-id-3",
+ "adm": "",
+ "mtype": 1
+ }
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 15,
+ "primary_category": "IAB1-5"
+ }
+ },
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801",
+ "impid": "test-imp-id-2",
+ "price": 10,
+ "adm": "some-test-ad-2",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 30,
+ "cat": [
+ "IAB1-1"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 30,
+ "primary_category": "IAB1-1"
+ }
+ }
+ ]
+ },
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e2",
+ "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547",
+ "price": 10,
+ "impid": "test-imp-id-3",
+ "adm": "",
+ "mtype": 1
+ },
+ "type": "banner"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/exemplary/video-app.json b/adapters/madsense/madsensetest/exemplary/video-app.json
new file mode 100644
index 00000000000..d3007dc2b83
--- /dev/null
+++ b/adapters/madsense/madsensetest/exemplary/video-app.json
@@ -0,0 +1,141 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "app": {
+ "bundle": "54321"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 15,
+ "primary_category": "IAB1-5"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/exemplary/video-web-pod.json b/adapters/madsense/madsensetest/exemplary/video-web-pod.json
new file mode 100644
index 00000000000..ce3e354cb60
--- /dev/null
+++ b/adapters/madsense/madsensetest/exemplary/video-web-pod.json
@@ -0,0 +1,212 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ },
+ {
+ "id": "test-imp-id-2",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+
+ ],
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "Origin": [
+ "domain.com"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ },
+ {
+ "id": "test-imp-id-2",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ }
+ },
+ "impIDs":["test-imp-id","test-imp-id-2"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801",
+ "impid": "test-imp-id-2",
+ "price": 10,
+ "adm": "some-test-ad-2",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 30,
+ "cat": [
+ "IAB1-1"
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 15,
+ "primary_category": "IAB1-5"
+ }
+ },
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801",
+ "impid": "test-imp-id-2",
+ "price": 10,
+ "adm": "some-test-ad-2",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 30,
+ "cat": [
+ "IAB1-1"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 30,
+ "primary_category": "IAB1-1"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/exemplary/video-web.json b/adapters/madsense/madsensetest/exemplary/video-web.json
new file mode 100644
index 00000000000..bf66a6470fd
--- /dev/null
+++ b/adapters/madsense/madsensetest/exemplary/video-web.json
@@ -0,0 +1,146 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "Origin": [
+ "domain.com"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "http://domain.com/page"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 15,
+ "primary_category": "IAB1-5"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-error.json b/adapters/madsense/madsensetest/supplemental/bad-response-error.json
new file mode 100644
index 00000000000..1ce30f8c3f3
--- /dev/null
+++ b/adapters/madsense/madsensetest/supplemental/bad-response-error.json
@@ -0,0 +1,93 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "app": {
+ "bundle": "54321"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": "invalid response"
+ }
+ }
+ ],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "Bad Server Response",
+ "comparison": "literal"
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-mtype.json b/adapters/madsense/madsensetest/supplemental/bad-response-mtype.json
new file mode 100644
index 00000000000..6c9c6c94a67
--- /dev/null
+++ b/adapters/madsense/madsensetest/supplemental/bad-response-mtype.json
@@ -0,0 +1,122 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "app": {
+ "bundle": "54321"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 4,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [{
+ "currency": "USD",
+ "bids": []
+ }],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "MType 4 not supported",
+ "comparison": "literal"
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-status-400.json b/adapters/madsense/madsensetest/supplemental/bad-response-status-400.json
new file mode 100644
index 00000000000..87424d2f86c
--- /dev/null
+++ b/adapters/madsense/madsensetest/supplemental/bad-response-status-400.json
@@ -0,0 +1,98 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "w": 1920,
+ "h": 1080,
+ "mimes": [
+ "video/x-flv",
+ "video/mp4"
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ua": "user-agent",
+ "ip": "1.2.3.4"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "page.com/test"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "Origin": [
+ "domain.com"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "w": 1920,
+ "h": 1080,
+ "mimes": [
+ "video/x-flv",
+ "video/mp4"
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ua": "user-agent",
+ "ip": "1.2.3.4"
+ },
+ "site": {
+ "domain": "domain.com",
+ "page": "page.com/test"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 400
+ }
+ }
+ ],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+ "comparison": "literal"
+ }
+ ]
+}
diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-status-500.json b/adapters/madsense/madsensetest/supplemental/bad-response-status-500.json
new file mode 100644
index 00000000000..143431c7144
--- /dev/null
+++ b/adapters/madsense/madsensetest/supplemental/bad-response-status-500.json
@@ -0,0 +1,92 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "app": {
+ "bundle": "54321"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 500
+ }
+ }
+ ],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "Unexpected status code: 500. Run with request.debug = 1 for more info",
+ "comparison": "literal"
+ }
+ ]
+}
+
diff --git a/adapters/madsense/madsensetest/supplemental/no-content-response.json b/adapters/madsense/madsensetest/supplemental/no-content-response.json
new file mode 100644
index 00000000000..27caa245cd3
--- /dev/null
+++ b/adapters/madsense/madsensetest/supplemental/no-content-response.json
@@ -0,0 +1,87 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "app": {
+ "bundle": "54321"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=9876543",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 204
+ }
+ }
+ ],
+ "expectedBidResponses": []
+}
+
diff --git a/adapters/madsense/madsensetest/supplemental/test-response.json b/adapters/madsense/madsensetest/supplemental/test-response.json
new file mode 100644
index 00000000000..9ef7c7894f4
--- /dev/null
+++ b/adapters/madsense/madsensetest/supplemental/test-response.json
@@ -0,0 +1,143 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "test": 1,
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "app": {
+ "bundle": "54321"
+ },
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "method": "POST",
+ "uri": "https://test.localhost.com?company_id=test",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ],
+ "X-Openrtb-Version": [
+ "2.6"
+ ],
+ "User-Agent": [
+ "user-agent"
+ ],
+ "X-Forwarded-For": [
+ "1.2.3.4"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "test": 1,
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "w": 1920,
+ "h": 1080
+ },
+ "ext": {
+ "bidder": {
+ "company_id": "9876543"
+ }
+ }
+ }
+ ],
+ "device": {
+ "ip": "1.2.3.4",
+ "ua": "user-agent"
+ },
+ "app": {
+ "bundle": "54321"
+ }
+ },
+ "impIDs":["test-imp-id"]
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ }
+ ],
+ "seat": "madsense"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+ "impid": "test-imp-id",
+ "price": 10,
+ "adm": "some-test-ad",
+ "crid": "54321",
+ "w": 1920,
+ "h": 1080,
+ "mtype": 2,
+ "dur": 15,
+ "cat": [
+ "IAB1-5",
+ "IAB1-6"
+ ]
+ },
+ "type": "video",
+ "video": {
+ "duration": 15,
+ "primary_category": "IAB1-5"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/adapters/madsense/params_test.go b/adapters/madsense/params_test.go
new file mode 100644
index 00000000000..6591767acc2
--- /dev/null
+++ b/adapters/madsense/params_test.go
@@ -0,0 +1,56 @@
+package madsense
+
+import (
+ "encoding/json"
+ "github.com/prebid/prebid-server/v3/openrtb_ext"
+ "testing"
+)
+
+// This file actually intends to test static/bidder-params/madsense.json
+//
+// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.madsense
+
+// TestValidParams makes sure that the madsense 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.BidderMadSense, json.RawMessage(validParam)); err != nil {
+ t.Errorf("Schema rejected madsense params: %s", validParam)
+ }
+ }
+}
+
+// TestInvalidParams makes sure that the madsense 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.BidderMadSense, json.RawMessage(invalidParam)); err == nil {
+ t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+ }
+ }
+}
+
+var validParams = []string{
+ `{"company_id": "9876543"}`,
+}
+
+var invalidParams = []string{
+ ``,
+ `null`,
+ `true`,
+ `5`,
+ `4.2`,
+ `[]`,
+ `{}`,
+ `{"companyId": "987654a"}`,
+ `{"companyId": "98765432"}`,
+ `{"company_id": ""}`,
+}
diff --git a/adapters/madsense/utils.go b/adapters/madsense/utils.go
new file mode 100644
index 00000000000..7ff97cd65f5
--- /dev/null
+++ b/adapters/madsense/utils.go
@@ -0,0 +1,99 @@
+package madsense
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v3/adapters"
+ "github.com/prebid/prebid-server/v3/errortypes"
+ "github.com/prebid/prebid-server/v3/openrtb_ext"
+ "github.com/prebid/prebid-server/v3/util/jsonutil"
+)
+
+func parseImpExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpMadSense, error) {
+ var bidderExt adapters.ExtImpBidder
+
+ if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil {
+ return nil, &errortypes.BadInput{
+ Message: fmt.Sprintf("Error while decoding extImpBidder, err: %v", err),
+ }
+ }
+
+ ext := openrtb_ext.ExtImpMadSense{}
+ err := jsonutil.Unmarshal(bidderExt.Bidder, &ext)
+ if err != nil {
+ return nil, &errortypes.BadInput{
+ Message: fmt.Sprintf("Error while decoding impExt, err: %v", err),
+ }
+ }
+
+ return &ext, nil
+}
+
+func getHeaders(request *openrtb2.BidRequest) http.Header {
+ headers := http.Header{}
+ headers.Add("Content-Type", "application/json;charset=utf-8")
+ headers.Add("Accept", "application/json")
+ headers.Add("X-Openrtb-Version", "2.6")
+
+ if request.Device != nil {
+ if len(request.Device.UA) > 0 {
+ headers.Add("User-Agent", request.Device.UA)
+ }
+
+ if len(request.Device.IP) > 0 {
+ headers.Add("X-Forwarded-For", request.Device.IP)
+ }
+
+ if len(request.Device.IPv6) > 0 {
+ headers.Add("X-Forwarded-For", request.Device.IPv6)
+ }
+ }
+
+ if request.Site != nil {
+ if request.Site.Domain != "" {
+ headers.Add("Origin", request.Site.Domain)
+ }
+ if request.Site.Ref != "" {
+ headers.Set("Referer", request.Site.Ref)
+ }
+ }
+ return headers
+}
+
+func getTypedBidFromBid(bid *openrtb2.Bid) (*adapters.TypedBid, error) {
+ bidType, err := getMediaTypeForBid(bid)
+ if err != nil {
+ return nil, err
+ }
+
+ var bidVideo *openrtb_ext.ExtBidPrebidVideo
+ if bidType == openrtb_ext.BidTypeVideo {
+ bidVideo = &openrtb_ext.ExtBidPrebidVideo{}
+ if len(bid.Cat) > 0 {
+ bidVideo.PrimaryCategory = bid.Cat[0]
+ }
+ if bid.Dur > 0 {
+ bidVideo.Duration = int(bid.Dur)
+ }
+ }
+ return &adapters.TypedBid{
+ Bid: bid,
+ BidType: bidType,
+ BidVideo: bidVideo,
+ }, nil
+}
+
+func getMediaTypeForBid(bid *openrtb2.Bid) (openrtb_ext.BidType, error) {
+ switch bid.MType {
+ case openrtb2.MarkupBanner:
+ return openrtb_ext.BidTypeBanner, nil
+ case openrtb2.MarkupVideo:
+ return openrtb_ext.BidTypeVideo, nil
+ default:
+ return "", &errortypes.BadServerResponse{
+ Message: fmt.Sprintf("MType %v not supported", bid.MType),
+ }
+ }
+}
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 3867cbde72b..0baf95b2d76 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -134,6 +134,7 @@ import (
"github.com/prebid/prebid-server/v3/adapters/loyal"
"github.com/prebid/prebid-server/v3/adapters/lunamedia"
"github.com/prebid/prebid-server/v3/adapters/mabidder"
+ "github.com/prebid/prebid-server/v3/adapters/madsense"
"github.com/prebid/prebid-server/v3/adapters/madvertise"
"github.com/prebid/prebid-server/v3/adapters/marsmedia"
"github.com/prebid/prebid-server/v3/adapters/mediago"
@@ -371,6 +372,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
openrtb_ext.BidderLoyal: loyal.Builder,
openrtb_ext.BidderLunaMedia: lunamedia.Builder,
openrtb_ext.BidderMabidder: mabidder.Builder,
+ openrtb_ext.BidderMadSense: madsense.Builder,
openrtb_ext.BidderMadvertise: madvertise.Builder,
openrtb_ext.BidderMarsmedia: marsmedia.Builder,
openrtb_ext.BidderMediafuse: appnexus.Builder,
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 894baf9a3bb..542d3998c59 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -151,6 +151,7 @@ var coreBidderNames []BidderName = []BidderName{
BidderLoyal,
BidderLunaMedia,
BidderMabidder,
+ BidderMadSense,
BidderMadvertise,
BidderMarsmedia,
BidderMediafuse,
@@ -493,6 +494,7 @@ const (
BidderLoyal BidderName = "loyal"
BidderLunaMedia BidderName = "lunamedia"
BidderMabidder BidderName = "mabidder"
+ BidderMadSense BidderName = "madsense"
BidderMadvertise BidderName = "madvertise"
BidderMarsmedia BidderName = "marsmedia"
BidderMediafuse BidderName = "mediafuse"
diff --git a/openrtb_ext/imp_madsense.go b/openrtb_ext/imp_madsense.go
new file mode 100644
index 00000000000..a0d4c0a6df0
--- /dev/null
+++ b/openrtb_ext/imp_madsense.go
@@ -0,0 +1,5 @@
+package openrtb_ext
+
+type ExtImpMadSense struct {
+ CompanyId string `json:"company_id"`
+}
diff --git a/static/bidder-info/madsense.yaml b/static/bidder-info/madsense.yaml
new file mode 100644
index 00000000000..4105c65fe98
--- /dev/null
+++ b/static/bidder-info/madsense.yaml
@@ -0,0 +1,12 @@
+endpoint: "https://ads.madsense.io/pbs"
+maintainer:
+ email: "prebid@madsense.io"
+capabilities:
+ app:
+ mediaTypes:
+ - banner
+ - video
+ site:
+ mediaTypes:
+ - banner
+ - video
\ No newline at end of file
diff --git a/static/bidder-params/madsense.json b/static/bidder-params/madsense.json
new file mode 100644
index 00000000000..54410fd2aee
--- /dev/null
+++ b/static/bidder-params/madsense.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "madSense Adapter Params",
+ "description": "A schema which validates params accepted by the madSense adapter",
+ "type": "object",
+ "properties": {
+ "company_id": {
+ "type": "string",
+ "description": "An id used to identify madSense company",
+ "minLength": 1
+ }
+ },
+ "required": ["company_id"]
+}