From 4a124781b11fc69ab2efc1faba8c2e1f6cbcc9a1 Mon Sep 17 00:00:00 2001 From: Kevin Kerr Date: Tue, 6 Aug 2019 19:36:47 -0400 Subject: [PATCH] TripleLift Prebid S2S Adapter (#954) * ignore swp files * start small * start really small * add a user sync * justify * triplelift adapter * add our endpoint * fix syntax * config stuff * compiler fixes * more config * add params * making progress * make our ext more exty * start making responses * more logic * fix compilation errors * can we just nil this out? * augment our json * radically simplify our json * fix errs * infer the bid type * fix syntax * fix comilation errors * rename * fix compilation error * config stuff * simplify params * more config stuff * fixes * revert this * fix up the extension * getting closer * add a test * update config * update bidder params * add the floor here, too * add a usersync test * validation, ws, and a test * update tests * fix test * update email * why not * change email * preprocess requests * do some parsing * take care of some errors * floor is optional * ws * remove native * everything is either banner or video * this should be a float * floor to floor * fix compilation errors * add some tests * more tests * more tests * simplify * more progress * format * ws * rm * don't need this * fix test * fix test * don't ignore swap * change line back * report an error if there are no valid impressions for triplelift * check for either a Banner or Video object on the impression * more tests * mv * more tests --- adapters/triplelift/triplelift.go | 147 ++++++++++++++++++ adapters/triplelift/triplelift_test.go | 10 ++ .../exemplary/optional-params.json | 66 ++++++++ .../exemplary/simple-banner.json | 125 +++++++++++++++ .../exemplary/simple-video.json | 114 ++++++++++++++ .../triplelifttest/supplemental/badext.json | 26 ++++ .../supplemental/badextbidder.json | 28 ++++ .../supplemental/badlyformed.json | 18 +++ .../supplemental/badresponseext.json | 99 ++++++++++++ .../supplemental/badstatuscode.json | 98 ++++++++++++ .../supplemental/notgoodstatuscode.json | 98 ++++++++++++ adapters/triplelift/usersync.go | 12 ++ adapters/triplelift/usersync_test.go | 19 +++ config/config.go | 2 + exchange/adapter_map.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_triplelift.go | 7 + static/bidder-info/triplelift.yaml | 11 ++ static/bidder-params/triplelift.json | 21 +++ usersync/usersyncers/syncer.go | 2 + usersync/usersyncers/syncer_test.go | 1 + 21 files changed, 908 insertions(+) create mode 100644 adapters/triplelift/triplelift.go create mode 100644 adapters/triplelift/triplelift_test.go create mode 100644 adapters/triplelift/triplelifttest/exemplary/optional-params.json create mode 100644 adapters/triplelift/triplelifttest/exemplary/simple-banner.json create mode 100644 adapters/triplelift/triplelifttest/exemplary/simple-video.json create mode 100644 adapters/triplelift/triplelifttest/supplemental/badext.json create mode 100644 adapters/triplelift/triplelifttest/supplemental/badextbidder.json create mode 100644 adapters/triplelift/triplelifttest/supplemental/badlyformed.json create mode 100644 adapters/triplelift/triplelifttest/supplemental/badresponseext.json create mode 100644 adapters/triplelift/triplelifttest/supplemental/badstatuscode.json create mode 100644 adapters/triplelift/triplelifttest/supplemental/notgoodstatuscode.json create mode 100644 adapters/triplelift/usersync.go create mode 100644 adapters/triplelift/usersync_test.go create mode 100644 openrtb_ext/imp_triplelift.go create mode 100644 static/bidder-info/triplelift.yaml create mode 100644 static/bidder-params/triplelift.json diff --git a/adapters/triplelift/triplelift.go b/adapters/triplelift/triplelift.go new file mode 100644 index 00000000000..b33ef8d0112 --- /dev/null +++ b/adapters/triplelift/triplelift.go @@ -0,0 +1,147 @@ +package triplelift + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" +) + +type TripleliftAdapter struct { + endpoint string +} + +type TripleliftInnerExt struct { + Format int `json:"format"` +} + +type TripleliftRespExt struct { + Triplelift TripleliftInnerExt `json:"triplelift_pb"` +} + +func getBidType(ext TripleliftRespExt) openrtb_ext.BidType { + t := ext.Triplelift.Format + if t == 11 { + return openrtb_ext.BidTypeVideo + } + return openrtb_ext.BidTypeBanner +} + +func processImp(imp *openrtb.Imp) error { + // get the triplelift extension + var ext adapters.ExtImpBidder + var tlext openrtb_ext.ExtImpTriplelift + if err := json.Unmarshal(imp.Ext, &ext); err != nil { + return err + } + if err := json.Unmarshal(ext.Bidder, &tlext); err != nil { + return err + } + if imp.Banner == nil && imp.Video == nil { + return fmt.Errorf("neither Banner nor Video object specified") + } + imp.TagID = tlext.InvCode + // floor is optional + if tlext.Floor == nil { + return nil + } else { + imp.BidFloor = *tlext.Floor + } + // no error + return nil +} + +func (a *TripleliftAdapter) MakeRequests(request *openrtb.BidRequest, extra *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + errs := make([]error, 0, len(request.Imp)+1) + reqs := make([]*adapters.RequestData, 0, 1) + // copy the request, because we are going to mutate it + tlRequest := *request + // this will contain all the valid impressions + var validImps []openrtb.Imp + // pre-process the imps + for _, imp := range tlRequest.Imp { + if err := processImp(&imp); err == nil { + validImps = append(validImps, imp) + } else { + errs = append(errs, err) + } + } + if len(validImps) == 0 { + err := fmt.Errorf("No valid impressions for triplelift") + errs = append(errs, err) + return nil, errs + } + tlRequest.Imp = validImps + reqJSON, err := json.Marshal(tlRequest) + if err != nil { + errs = append(errs, err) + return nil, errs + } + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + ad := a.endpoint + reqs = append(reqs, &adapters.RequestData{ + Method: "POST", + Uri: ad, + Body: reqJSON, + Headers: headers}) + return reqs, errs +} + +func getBidCount(bidResponse openrtb.BidResponse) int { + c := 0 + for _, sb := range bidResponse.SeatBid { + c = c + len(sb.Bid) + } + return c +} + +func (a *TripleliftAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if response.StatusCode == http.StatusNoContent { + return nil, nil + } + + if response.StatusCode == http.StatusBadRequest { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), + }} + } + + if response.StatusCode != http.StatusOK { + return nil, []error{fmt.Errorf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode)} + } + var bidResp openrtb.BidResponse + if err := json.Unmarshal(response.Body, &bidResp); err != nil { + return nil, []error{err} + } + var errs []error + count := getBidCount(bidResp) + bidResponse := adapters.NewBidderResponseWithBidsCapacity(count) + + for _, sb := range bidResp.SeatBid { + for i := 0; i < len(sb.Bid); i++ { + bid := sb.Bid[i] + var bidExt TripleliftRespExt + if err := json.Unmarshal(bid.Ext, &bidExt); err != nil { + errs = append(errs, err) + } else { + bidType := getBidType(bidExt) + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + }) + } + } + } + return bidResponse, errs +} + +func NewTripleliftBidder(client *http.Client, endpoint string) *TripleliftAdapter { + return &TripleliftAdapter{ + endpoint: endpoint} +} diff --git a/adapters/triplelift/triplelift_test.go b/adapters/triplelift/triplelift_test.go new file mode 100644 index 00000000000..0c167509688 --- /dev/null +++ b/adapters/triplelift/triplelift_test.go @@ -0,0 +1,10 @@ +package triplelift + +import ( + "github.com/prebid/prebid-server/adapters/adapterstest" + "testing" +) + +func TestJsonSamples(t *testing.T) { + adapterstest.RunJSONBidderTest(t, "triplelifttest", NewTripleliftBidder(nil, "http://tlx.3lift.net/s2s/auction?supplier_id=19")) +} diff --git a/adapters/triplelift/triplelifttest/exemplary/optional-params.json b/adapters/triplelift/triplelifttest/exemplary/optional-params.json new file mode 100644 index 00000000000..63b88c3a5fd --- /dev/null +++ b/adapters/triplelift/triplelifttest/exemplary/optional-params.json @@ -0,0 +1,66 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryCode": "foo", + "floor" : 20 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid": "foo", + "bidfloor": 20, + "ext": { + "bidder": { + "inventoryCode": "foo", + "floor" : 20 + } + } + } + ] + } + }, + "mockResponse": { + "status": 204 + } + } + ] +} diff --git a/adapters/triplelift/triplelifttest/exemplary/simple-banner.json b/adapters/triplelift/triplelifttest/exemplary/simple-banner.json new file mode 100644 index 00000000000..e7f59a81582 --- /dev/null +++ b/adapters/triplelift/triplelifttest/exemplary/simple-banner.json @@ -0,0 +1,125 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid" : "aa", + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "triplelift.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", + "cid": "958", + "crid": "29681110", + "h": 250, + "w": 300, + "ext": { + "triplelift_pb": { + "format" : 2 + } + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "adid": "29681110", + "adomain": [ + "triplelift.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", + "cid": "958", + "crid": "29681110", + "w": 300, + "h": 250, + "ext": { + "triplelift_pb": { + "format" : 2 + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/triplelift/triplelifttest/exemplary/simple-video.json b/adapters/triplelift/triplelifttest/exemplary/simple-video.json new file mode 100644 index 00000000000..5cf4296a815 --- /dev/null +++ b/adapters/triplelift/triplelifttest/exemplary/simple-video.json @@ -0,0 +1,114 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "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": { + "inventoryCode" : "aaw", + "floor" : 0.10 + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "body": { + "id": "test-request-id", + "imp": [ + { + "tagid" : "aaw", + "bidfloor" : 0.10, + "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": { + "inventoryCode": "aaw", + "floor" : 0.10 + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [{ + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.500000, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": ["foo.com"], + "iurl": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "cid": "958", + "crid": "29681110", + "h": 250, + "w": 300, + "cat": ["IAB9-1"], + "ext": {"triplelift_pb":{"format":11}} + }] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "adid": "29681110", + "adomain": ["foo.com"], + "iurl": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "cid": "958", + "crid": "29681110", + "w": 300, + "h": 250, + "cat": ["IAB9-1"], + "ext": { + "triplelift_pb": { + "format": 11 + } + } + }, + "type": "video" + } + ] + } + ] + } diff --git a/adapters/triplelift/triplelifttest/supplemental/badext.json b/adapters/triplelift/triplelifttest/supplemental/badext.json new file mode 100644 index 00000000000..df6a9b88be5 --- /dev/null +++ b/adapters/triplelift/triplelifttest/supplemental/badext.json @@ -0,0 +1,26 @@ +{ + "expectedMakeRequestsErrors" : ["json: cannot unmarshal string into Go value of type adapters.ExtImpBidder","No valid impressions for triplelift"], + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": "aaa" + } + ] + }, + "httpCalls": [ + ] +} diff --git a/adapters/triplelift/triplelifttest/supplemental/badextbidder.json b/adapters/triplelift/triplelifttest/supplemental/badextbidder.json new file mode 100644 index 00000000000..90651e4d8d2 --- /dev/null +++ b/adapters/triplelift/triplelifttest/supplemental/badextbidder.json @@ -0,0 +1,28 @@ +{ + "expectedMakeRequestsErrors" : ["json: cannot unmarshal string into Go value of type openrtb_ext.ExtImpTriplelift","No valid impressions for triplelift"], + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": "aaa" + } + } + ] + }, + "httpCalls":[], + "expectedBidResponses": [] +} diff --git a/adapters/triplelift/triplelifttest/supplemental/badlyformed.json b/adapters/triplelift/triplelifttest/supplemental/badlyformed.json new file mode 100644 index 00000000000..31d246bdeb7 --- /dev/null +++ b/adapters/triplelift/triplelifttest/supplemental/badlyformed.json @@ -0,0 +1,18 @@ +{ + "expectedMakeRequestsErrors" : ["neither Banner nor Video object specified","No valid impressions for triplelift"], + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + }, + "httpCalls": [ + ] +} diff --git a/adapters/triplelift/triplelifttest/supplemental/badresponseext.json b/adapters/triplelift/triplelifttest/supplemental/badresponseext.json new file mode 100644 index 00000000000..9c819add4ad --- /dev/null +++ b/adapters/triplelift/triplelifttest/supplemental/badresponseext.json @@ -0,0 +1,99 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid" : "aa", + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "triplelift.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", + "cid": "958", + "crid": "29681110", + "h": 250, + "w": 300, + "ext": "aaa" + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + ] + } + ], + "expectedMakeBidsErrors": ["json: cannot unmarshal string into Go value of type triplelift.TripleliftRespExt"] +} diff --git a/adapters/triplelift/triplelifttest/supplemental/badstatuscode.json b/adapters/triplelift/triplelifttest/supplemental/badstatuscode.json new file mode 100644 index 00000000000..18094a42758 --- /dev/null +++ b/adapters/triplelift/triplelifttest/supplemental/badstatuscode.json @@ -0,0 +1,98 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid" : "aa", + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + } + }, + "mockResponse": { + "status": 400, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "triplelift.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", + "cid": "958", + "crid": "29681110", + "h": 250, + "w": 300, + "ext": { + "triplelift_pb": { + "format" : 2 + } + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + ], + "expectedMakeBidsErrors": ["Unexpected status code: 400. Run with request.debug = 1 for more info"] +} diff --git a/adapters/triplelift/triplelifttest/supplemental/notgoodstatuscode.json b/adapters/triplelift/triplelifttest/supplemental/notgoodstatuscode.json new file mode 100644 index 00000000000..6332493c70a --- /dev/null +++ b/adapters/triplelift/triplelifttest/supplemental/notgoodstatuscode.json @@ -0,0 +1,98 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://tlx.3lift.net/s2s/auction?supplier_id=19", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "tagid" : "aa", + "ext": { + "bidder": { + "inventoryCode": "aa" + } + } + } + ] + } + }, + "mockResponse": { + "status": 302, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "triplelift.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", + "cid": "958", + "crid": "29681110", + "h": 250, + "w": 300, + "ext": { + "triplelift_pb": { + "format" : 2 + } + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + ], + "expectedMakeBidsErrors": ["Unexpected status code: 302. Run with request.debug = 1 for more info"] +} diff --git a/adapters/triplelift/usersync.go b/adapters/triplelift/usersync.go new file mode 100644 index 00000000000..5cb524bea11 --- /dev/null +++ b/adapters/triplelift/usersync.go @@ -0,0 +1,12 @@ +package triplelift + +import ( + "text/template" + + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/usersync" +) + +func NewTripleliftSyncer(temp *template.Template) usersync.Usersyncer { + return adapters.NewSyncer("triplelift", 28, temp, adapters.SyncTypeRedirect) +} diff --git a/adapters/triplelift/usersync_test.go b/adapters/triplelift/usersync_test.go new file mode 100644 index 00000000000..3406ec2a74b --- /dev/null +++ b/adapters/triplelift/usersync_test.go @@ -0,0 +1,19 @@ +package triplelift + +import ( + "testing" + "text/template" + + "github.com/stretchr/testify/assert" +) + +func TestTripleliftSyncer(t *testing.T) { + temp := template.Must(template.New("sync-template").Parse("//eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}")) + syncer := NewTripleliftSyncer(temp) + syncInfo, err := syncer.GetUsersyncInfo("", "") + assert.NoError(t, err) + assert.Equal(t, "//eb2.3lift.com/sync?gdpr=&cmp_cs=", syncInfo.URL) + assert.Equal(t, "redirect", syncInfo.Type) + assert.EqualValues(t, 28, syncer.GDPRVendorID()) + assert.Equal(t, false, syncInfo.SupportCORS) +} diff --git a/config/config.go b/config/config.go index 1329d9a1fe5..e096587fa55 100644 --- a/config/config.go +++ b/config/config.go @@ -450,6 +450,7 @@ func (cfg *Configuration) setDerivedDefaults() { setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldmo, "https://ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGamoshi, "https://rtb.gamoshi.io/pix/0000/scm?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgamoshi%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bgusr%5D") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderMgid, "https://cm.mgid.com/m?cdsp=363893&adu="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dmgid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7Bmuidn%7D") + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderTriplelift, "https://eb2.3lift.com/sync?gpdr={{.GDPR}}&cmp_cs={{.GDPRConsent}}") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderUnruly, "https://usermatch.targeting.unrulymedia.com/pbsync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&rurl="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dunruly%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderVisx, "https://t.visx.net/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") // openrtb_ext.BidderTappx doesn't have a good default. @@ -602,6 +603,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.rtbhouse.endpoint", "http://prebidserver-s2s-ams.creativecdn.com/bidder/prebidserver/bids") v.SetDefault("adapters.somoaudience.endpoint", "http://publisher-east.mobileadtrading.com/rtb/bid") v.SetDefault("adapters.sovrn.endpoint", "http://ap.lijit.com/rtb/bid?src=prebid_server") + v.SetDefault("adapters.triplelift.endpoint", "https://tlx.3lift.com/s2s/auction?supplier_id=19") v.SetDefault("adapters.adkerneladn.endpoint", "http://{{.Host}}/rtbpub?account={{.PublisherID}}") v.SetDefault("adapters.33across.partner_id", "") v.SetDefault("adapters.33across.endpoint", "http://ssc.33across.com/api/v1/hb") diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go index 673286cf042..a251920b516 100644 --- a/exchange/adapter_map.go +++ b/exchange/adapter_map.go @@ -37,6 +37,7 @@ import ( "github.com/prebid/prebid-server/adapters/sonobi" "github.com/prebid/prebid-server/adapters/sovrn" "github.com/prebid/prebid-server/adapters/tappx" + "github.com/prebid/prebid-server/adapters/triplelift" "github.com/prebid/prebid-server/adapters/unruly" "github.com/prebid/prebid-server/adapters/verizonmedia" "github.com/prebid/prebid-server/adapters/visx" @@ -79,6 +80,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter openrtb_ext.Bidder33Across: ttx.New33AcrossBidder(cfg.Adapters[string(openrtb_ext.Bidder33Across)].Endpoint), openrtb_ext.BidderGrid: grid.NewGridBidder(cfg.Adapters[string(openrtb_ext.BidderGrid)].Endpoint), openrtb_ext.BidderSonobi: sonobi.NewSonobiBidder(client, cfg.Adapters[string(openrtb_ext.BidderSonobi)].Endpoint), + openrtb_ext.BidderTriplelift: triplelift.NewTripleliftBidder(client, cfg.Adapters[string(openrtb_ext.BidderTriplelift)].Endpoint), openrtb_ext.BidderUnruly: unruly.NewUnrulyBidder(client, cfg.Adapters[string(openrtb_ext.BidderUnruly)].Endpoint), openrtb_ext.BidderVrtcal: vrtcal.NewVrtcalBidder(cfg.Adapters[string(openrtb_ext.BidderVrtcal)].Endpoint), openrtb_ext.BidderYieldmo: yieldmo.NewYieldmoBidder(cfg.Adapters[string(openrtb_ext.BidderYieldmo)].Endpoint), diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 3de7f28e5b8..b7ac5c5865b 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -50,6 +50,7 @@ const ( BidderSomoaudience BidderName = "somoaudience" BidderSovrn BidderName = "sovrn" BidderSonobi BidderName = "sonobi" + BidderTriplelift BidderName = "triplelift" BidderUnruly BidderName = "unruly" BidderVerizonMedia BidderName = "verizonmedia" BidderVrtcal BidderName = "vrtcal" @@ -90,6 +91,7 @@ var BidderMap = map[string]BidderName{ "somoaudience": BidderSomoaudience, "sovrn": BidderSovrn, "sonobi": BidderSonobi, + "triplelift": BidderTriplelift, "unruly": BidderUnruly, "verizonmedia": BidderVerizonMedia, "vrtcal": BidderVrtcal, diff --git a/openrtb_ext/imp_triplelift.go b/openrtb_ext/imp_triplelift.go new file mode 100644 index 00000000000..77ac9afdaf7 --- /dev/null +++ b/openrtb_ext/imp_triplelift.go @@ -0,0 +1,7 @@ +package openrtb_ext + +// ExtImpTriplelift defines the contract for bidrequest.imp[i].ext.triplelift +type ExtImpTriplelift struct { + InvCode string `json:"inventoryCode"` + Floor *float64 `json:"floor"` +} diff --git a/static/bidder-info/triplelift.yaml b/static/bidder-info/triplelift.yaml new file mode 100644 index 00000000000..2b9ff8d5675 --- /dev/null +++ b/static/bidder-info/triplelift.yaml @@ -0,0 +1,11 @@ +maintainer: + email: "prebid@triplelift.com" +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video diff --git a/static/bidder-params/triplelift.json b/static/bidder-params/triplelift.json new file mode 100644 index 00000000000..9f13045977d --- /dev/null +++ b/static/bidder-params/triplelift.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Triplelift Adapter Params", + "description": "A schema which validates params accepted by the Triplelift adapter", + + "type": "object", + "properties": { + "inventoryCode": { + "type": "string", + "description": "TripleLift inventory code for this ad unit (provided to you by your partner manager)" + }, + "floor" : {"description" : "the bid floor", "type": "number" } + }, + "oneOf": [{ + "oneOf": [{ + "required": ["inventoryCode"] + }] }], + "not": { + "required": ["floor"] + } +} diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go index e78915c93ff..cac8f9f53ad 100644 --- a/usersync/usersyncers/syncer.go +++ b/usersync/usersyncers/syncer.go @@ -35,6 +35,7 @@ import ( "github.com/prebid/prebid-server/adapters/somoaudience" "github.com/prebid/prebid-server/adapters/sonobi" "github.com/prebid/prebid-server/adapters/sovrn" + "github.com/prebid/prebid-server/adapters/triplelift" "github.com/prebid/prebid-server/adapters/unruly" "github.com/prebid/prebid-server/adapters/verizonmedia" "github.com/prebid/prebid-server/adapters/visx" @@ -79,6 +80,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync insertIntoMap(cfg, syncers, openrtb_ext.BidderSomoaudience, somoaudience.NewSomoaudienceSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderSovrn, sovrn.NewSovrnSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderSonobi, sonobi.NewSonobiSyncer) + insertIntoMap(cfg, syncers, openrtb_ext.BidderTriplelift, triplelift.NewTripleliftSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderVrtcal, vrtcal.NewVrtcalSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderYieldmo, yieldmo.NewYieldmoSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderVisx, visx.NewVisxSyncer) diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go index 454ac892b1c..5d1a0536d14 100644 --- a/usersync/usersyncers/syncer_test.go +++ b/usersync/usersyncers/syncer_test.go @@ -41,6 +41,7 @@ func TestNewSyncerMap(t *testing.T) { string(openrtb_ext.BidderSharethrough): syncConfig, string(openrtb_ext.BidderSomoaudience): syncConfig, string(openrtb_ext.BidderSovrn): syncConfig, + string(openrtb_ext.BidderTriplelift): syncConfig, string(openrtb_ext.Bidder33Across): syncConfig, string(openrtb_ext.BidderSonobi): syncConfig, string(openrtb_ext.BidderVrtcal): syncConfig,