diff --git a/adapters/dmx/dmx.go b/adapters/dmx/dmx.go
new file mode 100644
index 00000000000..6b4f698d4b1
--- /dev/null
+++ b/adapters/dmx/dmx.go
@@ -0,0 +1,296 @@
+package dmx
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "github.com/mxmCherry/openrtb"
+ "github.com/prebid/prebid-server/adapters"
+ "github.com/prebid/prebid-server/errortypes"
+ "github.com/prebid/prebid-server/openrtb_ext"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+type DmxAdapter struct {
+ endpoint string
+}
+
+func NewDmxBidder(endpoint string) *DmxAdapter {
+ return &DmxAdapter{endpoint: endpoint}
+}
+
+type dmxExt struct {
+ Bidder dmxParams `json:"bidder"`
+}
+
+type dmxParams struct {
+ TagId string `json:"tagid,omitempty"`
+ DmxId string `json:"dmxid,omitempty"`
+ MemberId string `json:"memberid,omitempty"`
+ PublisherId string `json:"publisher_id,omitempty"`
+ SellerId string `json:"seller_id,omitempty"`
+}
+
+func UserSellerOrPubId(str1, str2 string) string {
+ if str1 != "" {
+ return str1
+ }
+ return str2
+}
+
+func (adapter *DmxAdapter) MakeRequests(request *openrtb.BidRequest, req *adapters.ExtraRequestInfo) (reqsBidder []*adapters.RequestData, errs []error) {
+ var imps []openrtb.Imp
+ var rootExtInfo dmxExt
+ var publisherId string
+ var sellerId string
+ var userExt openrtb_ext.ExtUser
+ var anyHasId = false
+ var reqCopy openrtb.BidRequest = *request
+ var dmxReq *openrtb.BidRequest = &reqCopy
+
+ if request.User == nil {
+ if request.App == nil {
+ return nil, []error{errors.New("No user id or app id found. Could not send request to DMX.")}
+ }
+ }
+
+ if len(request.Imp) >= 1 {
+ err := json.Unmarshal(request.Imp[0].Ext, &rootExtInfo)
+ if err != nil {
+ errs = append(errs, err)
+ } else {
+ publisherId = UserSellerOrPubId(rootExtInfo.Bidder.PublisherId, rootExtInfo.Bidder.MemberId)
+ sellerId = rootExtInfo.Bidder.SellerId
+ }
+ }
+
+ if request.App != nil {
+ appCopy := *request.App
+ appPublisherCopy := *request.App.Publisher
+ dmxReq.App = &appCopy
+ dmxReq.App.Publisher = &appPublisherCopy
+ if dmxReq.App.ID != "" {
+ anyHasId = true
+ }
+ } else {
+ dmxReq.App = nil
+ }
+
+ if request.Site != nil {
+ siteCopy := *request.Site
+ sitePublisherCopy := *request.Site.Publisher
+ dmxReq.Site = &siteCopy
+ dmxReq.Site.Publisher = &sitePublisherCopy
+ if dmxReq.Site.Publisher != nil {
+ dmxReq.Site.Publisher.ID = publisherId
+ } else {
+ dmxReq.Site.Publisher = &openrtb.Publisher{ID: publisherId}
+ }
+ } else {
+ dmxReq.Site = nil
+ }
+
+ if request.User != nil {
+ userCopy := *request.User
+ dmxReq.User = &userCopy
+ } else {
+ dmxReq.User = nil
+ }
+
+ if dmxReq.User != nil {
+ if dmxReq.User.ID != "" {
+ anyHasId = true
+ }
+ if dmxReq.User.Ext != nil {
+ if err := json.Unmarshal(dmxReq.User.Ext, &userExt); err == nil {
+ if len(userExt.Eids) > 0 || (userExt.DigiTrust != nil && userExt.DigiTrust.ID != "") {
+ anyHasId = true
+ }
+ }
+ }
+ }
+
+ if anyHasId == false {
+ return nil, []error{errors.New("This request contained no identifier")}
+ }
+
+ for _, inst := range dmxReq.Imp {
+ var banner *openrtb.Banner
+ var video *openrtb.Video
+ var ins openrtb.Imp
+ var params dmxExt
+ const intVal int8 = 1
+ source := (*json.RawMessage)(&inst.Ext)
+ if err := json.Unmarshal(*source, ¶ms); err != nil {
+ errs = append(errs, err)
+ }
+ if isDmxParams(params.Bidder) {
+ if inst.Banner != nil {
+ if len(inst.Banner.Format) != 0 {
+ banner = inst.Banner
+ if params.Bidder.PublisherId != "" || params.Bidder.MemberId != "" {
+ imps = fetchParams(params, inst, ins, imps, banner, nil, intVal)
+ } else {
+ return nil, []error{errors.New("Missing Params for auction to be send")}
+ }
+ }
+ }
+
+ if inst.Video != nil {
+ video = inst.Video
+ if params.Bidder.PublisherId != "" || params.Bidder.MemberId != "" {
+ imps = fetchParams(params, inst, ins, imps, nil, video, intVal)
+ } else {
+ return nil, []error{errors.New("Missing Params for auction to be send")}
+ }
+ }
+ }
+
+ }
+
+ dmxReq.Imp = imps
+
+ oJson, err := json.Marshal(dmxReq)
+
+ if err != nil {
+ errs = append(errs, err)
+ return nil, errs
+ }
+
+ headers := http.Header{}
+ headers.Add("Content-Type", "Application/json;charset=utf-8")
+ reqBidder := &adapters.RequestData{
+ Method: "POST",
+ Uri: adapter.endpoint + addParams(sellerId), //adapter.endpoint,
+ Body: oJson,
+ Headers: headers,
+ }
+ reqsBidder = append(reqsBidder, reqBidder)
+ return
+}
+
+func (adapter *DmxAdapter) MakeBids(request *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+ var errs []error
+
+ if http.StatusNoContent == response.StatusCode {
+ return nil, nil
+ }
+
+ if http.StatusBadRequest == response.StatusCode {
+ return nil, []error{&errortypes.BadInput{
+ Message: fmt.Sprintf("Unexpected status code 400"),
+ }}
+ }
+
+ if http.StatusOK != response.StatusCode {
+ return nil, []error{&errortypes.BadInput{
+ Message: fmt.Sprintf("Unexpected response no status code"),
+ }}
+ }
+
+ var bidResp openrtb.BidResponse
+
+ if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+ return nil, []error{err}
+ }
+
+ bidResponse := adapters.NewBidderResponseWithBidsCapacity(5)
+
+ for _, sb := range bidResp.SeatBid {
+ for i := range sb.Bid {
+ bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, request.Imp)
+ if err != nil {
+ errs = append(errs, err)
+ } else {
+ b := &adapters.TypedBid{
+ Bid: &sb.Bid[i],
+ BidType: bidType,
+ }
+ if b.BidType == openrtb_ext.BidTypeVideo {
+ b.Bid.AdM = videoImpInsertion(b.Bid)
+ }
+ bidResponse.Bids = append(bidResponse.Bids, b)
+ }
+ }
+ }
+ return bidResponse, errs
+
+}
+
+func fetchParams(params dmxExt, inst openrtb.Imp, ins openrtb.Imp, imps []openrtb.Imp, banner *openrtb.Banner, video *openrtb.Video, intVal int8) []openrtb.Imp {
+ if params.Bidder.TagId != "" {
+ ins = openrtb.Imp{
+ ID: inst.ID,
+ TagID: params.Bidder.TagId,
+ Ext: inst.Ext,
+ Secure: &intVal,
+ }
+ }
+
+ if params.Bidder.DmxId != "" {
+ ins = openrtb.Imp{
+ ID: inst.ID,
+ TagID: params.Bidder.DmxId,
+ Ext: inst.Ext,
+ Secure: &intVal,
+ }
+ }
+ if banner != nil {
+ ins.Banner = banner
+ }
+
+ if video != nil {
+ ins.Video = video
+ }
+
+ if ins.TagID == "" {
+ return imps
+ }
+ imps = append(imps, ins)
+ return imps
+}
+
+func addParams(str string) string {
+ if str != "" {
+ return "?sellerid=" + url.QueryEscape(str)
+ }
+ return ""
+}
+
+func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType, error) {
+ mediaType := openrtb_ext.BidTypeBanner
+ for _, imp := range imps {
+ if imp.ID == impID {
+ if imp.Banner == nil && imp.Video != nil {
+ mediaType = openrtb_ext.BidTypeVideo
+ }
+ return mediaType, nil
+ }
+ }
+
+ // This shouldnt happen. Lets handle it just incase by returning an error.
+ return "", &errortypes.BadInput{
+ Message: fmt.Sprintf("Failed to find impression \"%s\" ", impID),
+ }
+}
+
+func videoImpInsertion(bid *openrtb.Bid) string {
+ adm := bid.AdM
+ nurl := bid.NURL
+ search := ""
+ imp := ""
+ wrapped_nurl := fmt.Sprintf(imp, nurl)
+ results := strings.Replace(adm, search, wrapped_nurl, 1)
+ return results
+}
+
+func isDmxParams(t interface{}) bool {
+ switch t.(type) {
+ case dmxParams:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/adapters/dmx/dmx_test.go b/adapters/dmx/dmx_test.go
new file mode 100644
index 00000000000..e9f195eb61d
--- /dev/null
+++ b/adapters/dmx/dmx_test.go
@@ -0,0 +1,782 @@
+package dmx
+
+import (
+ "encoding/json"
+ "github.com/mxmCherry/openrtb"
+ "github.com/prebid/prebid-server/adapters"
+ "strings"
+ "testing"
+
+ "github.com/prebid/prebid-server/adapters/adapterstest"
+)
+
+var (
+ bidRequest string
+)
+
+func TestFetchParams(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+ var arrImp []openrtb.Imp
+ var imps = fetchParams(
+ dmxExt{Bidder: dmxParams{
+ TagId: "222",
+ PublisherId: "5555",
+ }},
+ openrtb.Imp{ID: "32"},
+ openrtb.Imp{ID: "32"},
+ arrImp,
+ &openrtb.Banner{W: &width, H: &height, Format: []openrtb.Format{
+ {W: 300, H: 250},
+ }},
+ nil,
+ 1)
+ var imps2 = fetchParams(
+ dmxExt{Bidder: dmxParams{
+ DmxId: "222",
+ MemberId: "5555",
+ }},
+ openrtb.Imp{ID: "32"},
+ openrtb.Imp{ID: "32"},
+ arrImp,
+ &openrtb.Banner{W: &width, H: &height, Format: []openrtb.Format{
+ {W: 300, H: 250},
+ }},
+ nil,
+ 1)
+ if len(imps) == 0 {
+ t.Errorf("should increment the length by one")
+ }
+
+ if len(imps2) == 0 {
+ t.Errorf("should increment the length by one")
+ }
+
+}
+func TestJsonSamples(t *testing.T) {
+ adapterstest.RunJSONBidderTest(t, "dmxtest", new(DmxAdapter))
+}
+
+func TestMakeRequestsOtherPlacement(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ User: &openrtb.User{ID: "bscakucbkasucbkasunscancasuin"},
+ Imp: []openrtb.Imp{imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ ID: "1234",
+ }
+
+ actualAdapterRequests, err := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if actualAdapterRequests == nil {
+ t.Errorf("request should be nil")
+ }
+ if len(err) != 0 {
+ t.Errorf("We should have no error")
+ }
+
+}
+
+func TestMakeRequestsInvalid(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ ID: "1234",
+ }
+
+ actualAdapterRequests, err := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if len(actualAdapterRequests) != 0 {
+ t.Errorf("request should be nil")
+ }
+ if len(err) == 0 {
+ t.Errorf("We should have no error")
+ }
+
+}
+
+func TestMakeRequestNoSite(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1},
+ App: &openrtb.App{ID: "cansanuabnua", Publisher: &openrtb.Publisher{ID: "whatever"}},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("openrtb type should be an Array when it's an App")
+ }
+ var the_body openrtb.BidRequest
+ if err := json.Unmarshal(actualAdapterRequests[0].Body, &the_body); err != nil {
+ t.Errorf("failed to read bid request")
+ }
+
+ if the_body.App == nil {
+ t.Errorf("app property should be populated")
+ }
+
+ if the_body.App.Publisher.ID == "" {
+ t.Errorf("Missing publisher ID must be in")
+ }
+}
+
+func TestMakeRequestsApp(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ App: &openrtb.App{ID: "cansanuabnua", Publisher: &openrtb.Publisher{ID: "whatever"}},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("openrtb type should be an Array when it's an App")
+ }
+ var the_body openrtb.BidRequest
+ if err := json.Unmarshal(actualAdapterRequests[0].Body, &the_body); err != nil {
+ t.Errorf("failed to read bid request")
+ }
+
+ if the_body.App == nil {
+ t.Errorf("app property should be populated")
+ }
+
+}
+
+func TestMakeRequestsNoUser(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if actualAdapterRequests != nil {
+ t.Errorf("openrtb type should be empty")
+ }
+
+}
+
+func TestMakeRequests(t *testing.T) {
+ //server := httptest.NewServer(http.HandlerFunc(DummyDmxServer))
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+ imp2 := openrtb.Imp{
+ ID: "imp2",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+ imp3 := openrtb.Imp{
+ ID: "imp3",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1, imp2, imp3},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{ID: "districtmID"},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("should have 1 request")
+ }
+ var the_body openrtb.BidRequest
+ if err := json.Unmarshal(actualAdapterRequests[0].Body, &the_body); err != nil {
+ t.Errorf("failed to read bid request")
+ }
+
+ if len(the_body.Imp) != 3 {
+ t.Errorf("must have 3 bids")
+ }
+
+}
+
+func TestMakeBidVideo(t *testing.T) {
+ var w, h int = 640, 480
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Video: &openrtb.Video{
+ W: width,
+ H: height,
+ MIMEs: []string{"video/mp4"},
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{ID: "districtmID"},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("should have 1 request")
+ }
+ var the_body openrtb.BidRequest
+ if err := json.Unmarshal(actualAdapterRequests[0].Body, &the_body); err != nil {
+ t.Errorf("failed to read bid request")
+ }
+
+ if len(the_body.Imp) != 1 {
+ t.Errorf("must have 1 bids")
+ }
+}
+
+func TestMakeBidsNoContent(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{ID: "districtmID"},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+
+ _, err204 := adapter.MakeBids(&inputRequest, actualAdapterRequests[0], &adapters.ResponseData{StatusCode: 204})
+
+ if err204 != nil {
+ t.Errorf("Was expecting nil")
+ }
+
+ _, err400 := adapter.MakeBids(&inputRequest, actualAdapterRequests[0], &adapters.ResponseData{StatusCode: 400})
+
+ if err400 == nil {
+ t.Errorf("Was expecting error")
+ }
+
+ _, err500 := adapter.MakeBids(&inputRequest, actualAdapterRequests[0], &adapters.ResponseData{StatusCode: 500})
+
+ if err500 == nil {
+ t.Errorf("Was expecting error")
+ }
+
+ bidResponse := &adapters.ResponseData{
+ StatusCode: 200,
+ Body: []byte(`{
+ "id": "JdSgvXjee0UZ",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "16-40dbf1ef_0gKywr9JnzPAW4bE-1",
+ "impid": "imp1",
+ "price": 2.3456,
+ "adm": "",
+ "nurl": "dmxnotificationurlhere",
+ "adomain": [
+ "brand.com",
+ "advertiser.net"
+ ],
+ "cid": "12345",
+ "crid": "232303",
+ "cat": [
+ "IAB20-3"
+ ],
+ "attr": [
+ 2
+ ],
+ "w": 300,
+ "h": 600,
+ "language": "en"
+ }
+ ],
+ "seat": "10001"
+ }
+ ],
+ "cur": "USD"
+}`),
+ }
+
+ bidResponseNoMatch := &adapters.ResponseData{
+ StatusCode: 200,
+ Body: []byte(`{
+ "id": "JdSgvXjee0UZ",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "16-40dbf1ef_0gKywr9JnzPAW4bE-1",
+ "impid": "djvnsvns",
+ "price": 2.3456,
+ "adm": "",
+ "nurl": "dmxnotificationurlhere",
+ "adomain": [
+ "brand.com",
+ "advertiser.net"
+ ],
+ "cid": "12345",
+ "crid": "232303",
+ "cat": [
+ "IAB20-3"
+ ],
+ "attr": [
+ 2
+ ],
+ "w": 300,
+ "h": 600,
+ "language": "en"
+ }
+ ],
+ "seat": "10001"
+ }
+ ],
+ "cur": "USD"
+}`),
+ }
+
+ bids, _ := adapter.MakeBids(&inputRequest, actualAdapterRequests[0], bidResponse)
+ if bids == nil {
+ t.Errorf("ads not parse")
+ }
+ bidsNoMatching, _ := adapter.MakeBids(&inputRequest, actualAdapterRequests[0], bidResponseNoMatch)
+ if bidsNoMatching == nil {
+ t.Errorf("ads not parse")
+ }
+
+}
+func TestUserExtEmptyObject(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1, imp1, imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{Ext: json.RawMessage(`{}`)},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+ if len(actualAdapterRequests) != 0 {
+ t.Errorf("should have 0 request")
+ }
+}
+func TestUserEidsOnly(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1, imp1, imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{Ext: json.RawMessage(`{"eids": [{
+ "source": "adserver.org",
+ "uids": [{
+ "id": "111111111111",
+ "ext": {
+ "rtiPartner": "TDID"
+ }
+ }]
+ },{
+ "source": "netid.de",
+ "uids": [{
+ "id": "11111111"
+ }]
+ }]
+ }`)},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("should have 1 request")
+ }
+}
+
+func TestUserDigitrustOnly(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1, imp1, imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{Ext: json.RawMessage(`{
+ "digitrust": {
+ "id": "11111111111",
+ "keyv": 4
+ }}`)},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("should have 1 request")
+ }
+}
+
+func TestUsersEids(t *testing.T) {
+ var w, h int = 300, 250
+
+ var width, height uint64 = uint64(w), uint64(h)
+
+ adapter := NewDmxBidder("https://dmx.districtm.io/b/v2")
+ imp1 := openrtb.Imp{
+ ID: "imp1",
+ Ext: json.RawMessage("{\"bidder\":{\"dmxid\": \"1007\", \"memberid\": \"123456\", \"seller_id\":\"1008\"}}"),
+ Banner: &openrtb.Banner{
+ W: &width,
+ H: &height,
+ Format: []openrtb.Format{
+ {W: 300, H: 250},
+ },
+ }}
+
+ inputRequest := openrtb.BidRequest{
+ Imp: []openrtb.Imp{imp1, imp1, imp1},
+ Site: &openrtb.Site{
+ Publisher: &openrtb.Publisher{
+ ID: "10007",
+ },
+ },
+ User: &openrtb.User{ID: "districtmID", Ext: json.RawMessage(`{"eids": [{
+ "source": "adserver.org",
+ "uids": [{
+ "id": "111111111111",
+ "ext": {
+ "rtiPartner": "TDID"
+ }
+ }]
+ },{
+ "source": "pubcid.org",
+ "uids": [{
+ "id":"11111111"
+ }]
+ },
+ {
+ "source": "id5-sync.com",
+ "uids": [{
+ "id": "ID5-12345"
+ }]
+ },
+ {
+ "source": "parrable.com",
+ "uids": [{
+ "id": "01.1563917337.test-eid"
+ }]
+ },{
+ "source": "identityLink",
+ "uids": [{
+ "id": "11111111"
+ }]
+ },{
+ "source": "criteo",
+ "uids": [{
+ "id": "11111111"
+ }]
+ },{
+ "source": "britepool.com",
+ "uids": [{
+ "id": "11111111"
+ }]
+ },{
+ "source": "liveintent.com",
+ "uids": [{
+ "id": "11111111"
+ }]
+ },{
+ "source": "netid.de",
+ "uids": [{
+ "id": "11111111"
+ }]
+ }],
+ "digitrust": {
+ "id": "11111111111",
+ "keyv": 4
+ }}`)},
+ ID: "1234",
+ }
+
+ actualAdapterRequests, _ := adapter.MakeRequests(&inputRequest, &adapters.ExtraRequestInfo{})
+ if len(actualAdapterRequests) != 1 {
+ t.Errorf("should have 1 request")
+ }
+ var the_body openrtb.BidRequest
+ if err := json.Unmarshal(actualAdapterRequests[0].Body, &the_body); err != nil {
+ t.Errorf("failed to read bid request")
+ }
+
+ if len(the_body.Imp) != 3 {
+ t.Errorf("must have 3 bids")
+ }
+}
+func TestVideoImpInsertion(t *testing.T) {
+ var bidResp openrtb.BidResponse
+ var bid openrtb.Bid
+ payload := []byte(`{
+ "id": "some-request-id",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "video1",
+ "impid": "video1",
+ "price": 5.01,
+ "nurl": "https://demo.arripiblik.com/359585167267151",
+ "adm": "BidSwitch",
+ "crid": "76575664756",
+ "dealid": "dmx-deal-hp-24",
+ "w": 640,
+ "h": 480,
+ "ext": {
+ "prebid": {
+ "type": "video"
+ }
+ }
+ },
+ {
+ "id": "some-impression-id",
+ "impid": "some-impression-id",
+ "price": 5.01,
+ "adm": "",
+ "crid": "1346943998",
+ "dealid": "dmx-deal-hp-24",
+ "w": 300,
+ "h": 250,
+ "ext": {
+ "prebid": {
+ "type": "banner"
+ }
+ }
+ },
+ {
+ "id": "some-impression-id2",
+ "impid": "some-impression-id2",
+ "price": 5.01,
+ "adm": "",
+ "crid": "1424798162",
+ "dealid": "dmx-deal-hp-24",
+ "w": 728,
+ "h": 90,
+ "ext": {
+ "prebid": {
+ "type": "banner"
+ }
+ }
+ }
+ ],
+ "seat": "dmx"
+ }
+ ]
+}`)
+
+ err := json.Unmarshal(payload, &bidResp)
+ if err != nil {
+ t.Errorf("Payload is invalid")
+ }
+ bid = openrtb.Bid(bidResp.SeatBid[0].Bid[0])
+ data := videoImpInsertion(&bid)
+ find := strings.Index(data, "demo.arripiblik.com")
+ if find == -1 {
+ t.Errorf("String was not found")
+ }
+
+}
diff --git a/adapters/dmx/dmxtest/exemplary/simple-app.json b/adapters/dmx/dmxtest/exemplary/simple-app.json
new file mode 100644
index 00000000000..a2d57163f3c
--- /dev/null
+++ b/adapters/dmx/dmxtest/exemplary/simple-app.json
@@ -0,0 +1,138 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "app":{
+ "bundle":"302324249",
+ "id":"ed6207cefff74c14878963566683c070",
+ "name":"Skout - iOS Match Buy",
+ "publisher":{
+ "id":"10400"
+ },
+ "storeurl":"https://itunes.apple.com/app/id302324249"
+ },
+ "imp": [
+ {
+
+ "id": "test-imp-id",
+ "banner": {
+ "w": 300,
+ "h": 250,
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "dmxid": "123454",
+ "publisher_id": "10400"
+ }
+ }
+ }
+ ]
+ },
+
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "",
+ "body": {
+ "id": "test-request-id",
+ "app":{
+ "bundle":"302324249",
+ "id":"ed6207cefff74c14878963566683c070",
+ "name":"Skout - iOS Match Buy",
+ "publisher":{
+ "id":"10400"
+ },
+ "storeurl":"https://itunes.apple.com/app/id302324249"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "tagid": "123454",
+ "secure": 1,
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ],
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "publisher_id": "10400",
+ "dmxid": "123454"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "seat": "958",
+ "bid": [{
+ "id": "7706636740145184841",
+ "impid": "test-imp-id",
+ "price": 1.75,
+ "adid": "29681110",
+ "adm": "
banner-ads
",
+ "adomain": ["dmx.districtm.io"],
+ "iurl": "https://dmx.districtm.io/b/v2",
+ "cid": "958",
+ "crid": "29681110",
+ "h": 250,
+ "w": 300
+ }]
+ }
+ ],
+ "bidid": "5778926625248726496",
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "7706636740145184841",
+ "impid": "test-imp-id",
+ "price": 1.75,
+ "adm": "banner-ads
",
+ "adid": "29681110",
+ "adomain": ["dmx.districtm.io"],
+ "iurl": "https://dmx.districtm.io/b/v2",
+ "cid": "958",
+ "crid": "29681110",
+ "w": 300,
+ "h": 250
+
+ },
+ "type": "banner"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/adapters/dmx/dmxtest/exemplary/simple-banner.json b/adapters/dmx/dmxtest/exemplary/simple-banner.json
new file mode 100644
index 00000000000..03ea6246ee4
--- /dev/null
+++ b/adapters/dmx/dmxtest/exemplary/simple-banner.json
@@ -0,0 +1,126 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "user": {
+ "id": "fhacacnasicnaic"
+ },
+ "imp": [
+ {
+
+ "id": "test-imp-id",
+ "banner": {
+ "w": 300,
+ "h": 250,
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "dmxid": "123454",
+ "publisher_id": "10400"
+ }
+ }
+ }
+ ]
+ },
+
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "",
+ "body": {
+ "id": "test-request-id",
+ "user": {
+ "id": "fhacacnasicnaic"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "tagid": "123454",
+ "secure": 1,
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ],
+ "w": 300,
+ "h": 250
+ },
+ "ext": {
+ "bidder": {
+ "publisher_id": "10400",
+ "dmxid": "123454"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "seat": "958",
+ "bid": [{
+ "id": "7706636740145184841",
+ "impid": "test-imp-id",
+ "price": 1.75,
+ "adid": "29681110",
+ "adm": "banner-ads
",
+ "adomain": ["dmx.districtm.io"],
+ "iurl": "https://dmx.districtm.io/b/v2",
+ "cid": "958",
+ "crid": "29681110",
+ "h": 250,
+ "w": 300
+ }]
+ }
+ ],
+ "bidid": "5778926625248726496",
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "7706636740145184841",
+ "impid": "test-imp-id",
+ "price": 1.75,
+ "adm": "banner-ads
",
+ "adid": "29681110",
+ "adomain": ["dmx.districtm.io"],
+ "iurl": "https://dmx.districtm.io/b/v2",
+ "cid": "958",
+ "crid": "29681110",
+ "w": 300,
+ "h": 250
+
+ },
+ "type": "banner"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/adapters/dmx/dmxtest/exemplary/simple-video.json b/adapters/dmx/dmxtest/exemplary/simple-video.json
new file mode 100644
index 00000000000..b4c53188119
--- /dev/null
+++ b/adapters/dmx/dmxtest/exemplary/simple-video.json
@@ -0,0 +1,112 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "user": {
+ "id": "whateveryouwant"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": ["video/mp4"],
+ "minduration": 15,
+ "maxduration": 30,
+ "protocols": [2, 3, 5, 6, 7, 8],
+ "w": 940,
+ "h": 560
+ },
+ "ext": {
+ "bidder": {
+ "tagid": "12345",
+ "publisher_id": "10400"
+ }
+ }
+ }
+ ]
+ },
+
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "",
+ "body": {
+ "id": "test-request-id",
+ "user": {
+ "id": "whateveryouwant"
+ },
+ "imp": [
+ {
+ "ext": {
+ "bidder": {
+ "tagid": "12345",
+ "publisher_id": "10400"
+ }
+ },
+ "id": "test-imp-id",
+ "tagid": "12345",
+ "secure": 1,
+ "video": {
+ "mimes": ["video/mp4"],
+ "minduration": 15,
+ "maxduration": 30,
+ "protocols": [2, 3, 5, 6, 7, 8],
+ "w": 940,
+ "h": 560
+ }
+ }
+ ]
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "seat": "958",
+ "bid": [{
+ "id": "7706636740145184841",
+ "impid": "test-imp-id",
+ "price": 1.90,
+ "adid": "29681110",
+ "adm": "ads",
+ "adomain": ["dmx.districtm.io"],
+ "iurl": "https://dmx.districtm.io/b/v2",
+ "cid": "958",
+ "crid": "29681110",
+ "h": 250,
+ "w": 300
+ }]
+ }
+ ],
+ "bidid": "5778926625248726496",
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "7706636740145184841",
+ "impid": "test-imp-id",
+ "price": 1.90,
+ "adm": "ads",
+ "adid": "29681110",
+ "adomain": ["dmx.districtm.io"],
+ "iurl": "https://dmx.districtm.io/b/v2",
+ "cid": "958",
+ "crid": "29681110",
+ "w": 300,
+ "h": 250
+ },
+ "type": "video"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/adapters/dmx/dmxtest/params/race/banner.json b/adapters/dmx/dmxtest/params/race/banner.json
new file mode 100644
index 00000000000..1c0adff78ac
--- /dev/null
+++ b/adapters/dmx/dmxtest/params/race/banner.json
@@ -0,0 +1,4 @@
+{
+ "tagid": "25251",
+ "publisher_id": "100152"
+}
\ No newline at end of file
diff --git a/adapters/dmx/dmxtest/params/race/video.json b/adapters/dmx/dmxtest/params/race/video.json
new file mode 100644
index 00000000000..3bbd83bd3b0
--- /dev/null
+++ b/adapters/dmx/dmxtest/params/race/video.json
@@ -0,0 +1,4 @@
+{
+ "tagid": "25255",
+ "publisher_id": "100151"
+}
\ No newline at end of file
diff --git a/adapters/dmx/usersync.go b/adapters/dmx/usersync.go
new file mode 100644
index 00000000000..98e56234fa6
--- /dev/null
+++ b/adapters/dmx/usersync.go
@@ -0,0 +1,12 @@
+package dmx
+
+import (
+ "text/template"
+
+ "github.com/prebid/prebid-server/adapters"
+ "github.com/prebid/prebid-server/usersync"
+)
+
+func NewDmxSyncer(temp *template.Template) usersync.Usersyncer {
+ return adapters.NewSyncer("dmx", 144, temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/dmx/usersync_test.go b/adapters/dmx/usersync_test.go
new file mode 100644
index 00000000000..e4e3c7d8e55
--- /dev/null
+++ b/adapters/dmx/usersync_test.go
@@ -0,0 +1,20 @@
+package dmx
+
+import (
+ "github.com/prebid/prebid-server/privacy"
+ "testing"
+ "text/template"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestDmxSyncer(t *testing.T) {
+ temp := template.Must(template.New("sync-template").Parse("https://dmx.districtm.io/s/v1/img/s/10007"))
+ syncer := NewDmxSyncer(temp)
+ syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{})
+ assert.NoError(t, err)
+ assert.Equal(t, "https://dmx.districtm.io/s/v1/img/s/10007", syncInfo.URL)
+ assert.Equal(t, "redirect", syncInfo.Type)
+ assert.EqualValues(t, 144, syncer.GDPRVendorID())
+ assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/config/config.go b/config/config.go
index 9652ae141f5..e93aed46eab 100755
--- a/config/config.go
+++ b/config/config.go
@@ -534,6 +534,7 @@ func (cfg *Configuration) setDerivedDefaults() {
setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderConversant, "https://prebid-match.dotomi.com/match/bounce/current?version=1&networkId=72582&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dconversant%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderCpmstar, "https://server.cpmstar.com/usersync.aspx?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dcpmstar%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDatablocks, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D")
+ setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDmx, "https://dmx.districtm.io/s/v1/img/s/10007?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D%24%7Bgdpr%7D%26gdpr_consent%3D%24%7Bgdpr_consent%7D%26uid%3D%24%7Buid%7D")
setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEmxDigital, "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID")
setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEngageBDR, "https://match.bnmla.com/usersync/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")
setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEPlanning, "https://ads.us.e-planning.net/uspd/1/?du="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Deplanning%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
@@ -711,9 +712,10 @@ func SetupViper(v *viper.Viper, filename string) {
// for them and specify all the parameters they need for them to work correctly.
v.SetDefault("adapters.audiencenetwork.disabled", true)
v.SetDefault("adapters.rubicon.disabled", true)
-
v.SetDefault("adapters.33across.endpoint", "http://ssc.33across.com/api/v1/hb")
v.SetDefault("adapters.33across.partner_id", "")
+ v.SetDefault("adapters.dmx.endpoint", "https://dmx.districtm.io/b/v2")
+ v.SetDefault("adapters.adtelligent.endpoint", "http://hb.adtelligent.com/auction")
v.SetDefault("adapters.adform.endpoint", "http://adx.adform.net/adx")
v.SetDefault("adapters.adgeneration.endpoint", "https://d.socdm.com/adsv/v1")
v.SetDefault("adapters.adhese.endpoint", "https://ads-{{.AccountID}}.adhese.com/json")
diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go
index b69b5b50e13..390016117fb 100755
--- a/exchange/adapter_map.go
+++ b/exchange/adapter_map.go
@@ -29,6 +29,7 @@ import (
"github.com/prebid/prebid-server/adapters/conversant"
"github.com/prebid/prebid-server/adapters/cpmstar"
"github.com/prebid/prebid-server/adapters/datablocks"
+ "github.com/prebid/prebid-server/adapters/dmx"
"github.com/prebid/prebid-server/adapters/emx_digital"
"github.com/prebid/prebid-server/adapters/engagebdr"
"github.com/prebid/prebid-server/adapters/eplanning"
@@ -107,6 +108,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
openrtb_ext.BidderConsumable: consumable.NewConsumableBidder(cfg.Adapters[string(openrtb_ext.BidderConsumable)].Endpoint),
openrtb_ext.BidderCpmstar: cpmstar.NewCpmstarBidder(cfg.Adapters[string(openrtb_ext.BidderCpmstar)].Endpoint),
openrtb_ext.BidderDatablocks: datablocks.NewDatablocksBidder(cfg.Adapters[string(openrtb_ext.BidderDatablocks)].Endpoint),
+ openrtb_ext.BidderDmx: dmx.NewDmxBidder(cfg.Adapters[string(openrtb_ext.BidderDmx)].Endpoint),
openrtb_ext.BidderEmxDigital: emx_digital.NewEmxDigitalBidder(cfg.Adapters[string(openrtb_ext.BidderEmxDigital)].Endpoint),
openrtb_ext.BidderEngageBDR: engagebdr.NewEngageBDRBidder(client, cfg.Adapters[string(openrtb_ext.BidderEngageBDR)].Endpoint),
openrtb_ext.BidderEPlanning: eplanning.NewEPlanningBidder(client, cfg.Adapters[string(openrtb_ext.BidderEPlanning)].Endpoint),
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 8a53e4adcf2..b3ecddb06cd 100755
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -46,6 +46,7 @@ const (
BidderConversant BidderName = "conversant"
BidderCpmstar BidderName = "cpmstar"
BidderDatablocks BidderName = "datablocks"
+ BidderDmx BidderName = "dmx"
BidderEmxDigital BidderName = "emx_digital"
BidderEngageBDR BidderName = "engagebdr"
BidderEPlanning BidderName = "eplanning"
@@ -122,6 +123,7 @@ var BidderMap = map[string]BidderName{
"conversant": BidderConversant,
"cpmstar": BidderCpmstar,
"datablocks": BidderDatablocks,
+ "dmx": BidderDmx,
"emx_digital": BidderEmxDigital,
"engagebdr": BidderEngageBDR,
"eplanning": BidderEPlanning,
diff --git a/static/bidder-info/dmx.yaml b/static/bidder-info/dmx.yaml
new file mode 100644
index 00000000000..d6e54178db4
--- /dev/null
+++ b/static/bidder-info/dmx.yaml
@@ -0,0 +1,11 @@
+maintainer:
+ email: "steve@districtm.net"
+capabilities:
+ site:
+ mediaTypes:
+ - banner
+ - video
+ app:
+ mediaTypes:
+ - banner
+ - video
diff --git a/static/bidder-params/dmx.json b/static/bidder-params/dmx.json
new file mode 100644
index 00000000000..4c0df65e3d4
--- /dev/null
+++ b/static/bidder-params/dmx.json
@@ -0,0 +1,22 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "District M DMX Adapter Params",
+ "description": "A schema which validates params accepted by the DMX adapter",
+ "type": "object",
+ "properties": {
+ "memberid" : {
+ "type": "string",
+ "description": "Represent boost MemberId from districtm UI"
+ },
+ "tagid": {
+ "type": "string",
+ "description": "Represent the placement ID, this value is optional"
+ },
+ "bidfloor": {
+ "type": "string",
+ "description": "The minimum price acceptable for a bid"
+ }
+ },
+
+ "required": ["memberid"]
+}
\ No newline at end of file
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
index 791a00de0a9..5dccf855add 100755
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -24,6 +24,7 @@ import (
"github.com/prebid/prebid-server/adapters/conversant"
"github.com/prebid/prebid-server/adapters/cpmstar"
"github.com/prebid/prebid-server/adapters/datablocks"
+ "github.com/prebid/prebid-server/adapters/dmx"
"github.com/prebid/prebid-server/adapters/emx_digital"
"github.com/prebid/prebid-server/adapters/engagebdr"
"github.com/prebid/prebid-server/adapters/eplanning"
@@ -94,6 +95,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
insertIntoMap(cfg, syncers, openrtb_ext.BidderConversant, conversant.NewConversantSyncer)
insertIntoMap(cfg, syncers, openrtb_ext.BidderCpmstar, cpmstar.NewCpmstarSyncer)
insertIntoMap(cfg, syncers, openrtb_ext.BidderDatablocks, datablocks.NewDatablocksSyncer)
+ insertIntoMap(cfg, syncers, openrtb_ext.BidderDmx, dmx.NewDmxSyncer)
insertIntoMap(cfg, syncers, openrtb_ext.BidderEmxDigital, emx_digital.NewEMXDigitalSyncer)
insertIntoMap(cfg, syncers, openrtb_ext.BidderEngageBDR, engagebdr.NewEngageBDRSyncer)
insertIntoMap(cfg, syncers, openrtb_ext.BidderEPlanning, eplanning.NewEPlanningSyncer)
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index 9aae284da2a..ddd067e8be7 100755
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -32,6 +32,7 @@ func TestNewSyncerMap(t *testing.T) {
string(openrtb_ext.BidderConversant): syncConfig,
string(openrtb_ext.BidderCpmstar): syncConfig,
string(openrtb_ext.BidderDatablocks): syncConfig,
+ string(openrtb_ext.BidderDmx): syncConfig,
string(openrtb_ext.BidderEmxDigital): syncConfig,
string(openrtb_ext.BidderEngageBDR): syncConfig,
string(openrtb_ext.BidderEPlanning): syncConfig,