diff --git a/adapters/adapterstest/test_json.go b/adapters/adapterstest/test_json.go index 7602ab16e41..8fdb9c5d9d6 100644 --- a/adapters/adapterstest/test_json.go +++ b/adapters/adapterstest/test_json.go @@ -208,7 +208,7 @@ func diffErrorLists(t *testing.T, description string, actual []error, expected [ t.Helper() if len(expected) != len(actual) { - t.Fatalf("%s had wrong error count. Expected %d, got %d", description, len(expected), len(actual)) + t.Fatalf("%s had wrong error count. Expected %d, got %d (%v)", description, len(expected), len(actual), actual) } for i := 0; i < len(actual); i++ { if expected[i].Comparison == "literal" { diff --git a/adapters/yieldlab/const.go b/adapters/yieldlab/const.go new file mode 100644 index 00000000000..cb66cb6db17 --- /dev/null +++ b/adapters/yieldlab/const.go @@ -0,0 +1,7 @@ +package yieldlab + +const adSlotIdSeparator = "," +const adsizeSeparator = "x" +const adSourceBanner = "" +const adSourceURL = "https://ad.yieldlab.net/d/%v/%v/%v?%v" +const creativeID = "%v%v%v" diff --git a/adapters/yieldlab/params_test.go b/adapters/yieldlab/params_test.go new file mode 100644 index 00000000000..8c230c15b15 --- /dev/null +++ b/adapters/yieldlab/params_test.go @@ -0,0 +1,63 @@ +package yieldlab + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/openrtb_ext" +) + +// This file actually intends to test static/bidder-params/yieldlab.json +// +// These also validate the format of the external API: request.imp[i].ext.yieldlab + +// TestValidParams makes sure that the yieldlab 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.BidderYieldlab, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected yieldlab params: %s", validParam) + } + } +} + +// TestInvalidParams makes sure that the yieldlab 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.BidderYieldlab, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"adslotId": "123","supplyId":"23456","adSize":"100x100"}`, + `{"adslotId": "123","supplyId":"23456","adSize":"100x100","extId":"asdf"}`, + `{"adslotId": "123","supplyId":"23456","adSize":"100x100","extId":"asdf","targeting":{"a":"b"}}`, + `{"adslotId": "123","supplyId":"23456","adSize":"100x100","targeting":{"a":"b"}}`, + `{"adslotId": "123","supplyId":"23456","adSize":"100x100","targeting":{"a":"b"}}`, +} + +var invalidParams = []string{ + `{"supplyId":"23456","adSize":"100x100"}`, + `{"adslotId": "123","adSize":"100x100","extId":"asdf"}`, + `{"adslotId": "123","supplyId":"23456","extId":"asdf","targeting":{"a":"b"}}`, + `{"adslotId": "123","supplyId":"23456"}`, + `{"adSize":"100x100","supplyId":"23456"}`, + `{"adslotId": "123","adSize":"100x100"}`, + `{"supplyId":"23456"}`, + `{"adslotId": "123"}`, + `{}`, + `[]`, + `{"a":"b"}`, + `null`, +} diff --git a/adapters/yieldlab/types.go b/adapters/yieldlab/types.go new file mode 100644 index 00000000000..90612700713 --- /dev/null +++ b/adapters/yieldlab/types.go @@ -0,0 +1,29 @@ +package yieldlab + +import ( + "strconv" + "time" +) + +type bidResponse struct { + ID uint64 `json:"id"` + Price uint `json:"price"` + Advertiser string `json:"advertiser"` + Adsize string `json:"adsize"` + Pid uint64 `json:"pid"` + Did uint64 `json:"did"` + Pvid string `json:"pvid"` +} + +type cacheBuster func() string + +type weekGenerator func() string + +var defaultCacheBuster cacheBuster = func() string { + return strconv.FormatInt(time.Now().Unix(), 10) +} + +var defaultWeekGenerator weekGenerator = func() string { + _, week := time.Now().ISOWeek() + return strconv.Itoa(week) +} diff --git a/adapters/yieldlab/usersync.go b/adapters/yieldlab/usersync.go new file mode 100644 index 00000000000..3ee9a3fdfb5 --- /dev/null +++ b/adapters/yieldlab/usersync.go @@ -0,0 +1,12 @@ +package yieldlab + +import ( + "text/template" + + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/usersync" +) + +func NewYieldlabSyncer(temp *template.Template) usersync.Usersyncer { + return adapters.NewSyncer("yieldlab", 70, temp, adapters.SyncTypeRedirect) +} diff --git a/adapters/yieldlab/usersync_test.go b/adapters/yieldlab/usersync_test.go new file mode 100644 index 00000000000..3892c16bf05 --- /dev/null +++ b/adapters/yieldlab/usersync_test.go @@ -0,0 +1,26 @@ +package yieldlab + +import ( + "testing" + "text/template" + + "github.com/stretchr/testify/assert" + + "github.com/prebid/prebid-server/privacy" + "github.com/prebid/prebid-server/privacy/gdpr" +) + +func TestYieldlabSyncer(t *testing.T) { + temp := template.Must(template.New("sync-template").Parse("https://ad.yieldlab.net/mr?t=2&pid=9140838&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldlab%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25YL_UID%25%25")) + syncer := NewYieldlabSyncer(temp) + syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{ + GDPR: gdpr.Policy{ + Signal: "0", + }, + }) + assert.NoError(t, err) + assert.Equal(t, "https://ad.yieldlab.net/mr?t=2&pid=9140838&gdpr=0&gdpr_consent=&redirectUri=http%3A%2F%2Flocalhost%2F%2Fsetuid%3Fbidder%3Dyieldlab%26gdpr%3D0%26gdpr_consent%3D%26uid%3D%25%25YL_UID%25%25", syncInfo.URL) + assert.Equal(t, "redirect", syncInfo.Type) + assert.EqualValues(t, 70, syncer.GDPRVendorID()) + assert.False(t, syncInfo.SupportCORS) +} diff --git a/adapters/yieldlab/yieldlab.go b/adapters/yieldlab/yieldlab.go new file mode 100644 index 00000000000..20f3674797d --- /dev/null +++ b/adapters/yieldlab/yieldlab.go @@ -0,0 +1,314 @@ +package yieldlab + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + "path" + "strconv" + "strings" + + "github.com/mxmCherry/openrtb" + "golang.org/x/text/currency" + + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" +) + +// YieldlabAdapter connects the Yieldlab API to prebid server +type YieldlabAdapter struct { + endpoint string + cacheBuster cacheBuster + getWeek weekGenerator +} + +// NewYieldlabBidder returns a new YieldlabBidder instance +func NewYieldlabBidder(endpoint string) *YieldlabAdapter { + return &YieldlabAdapter{ + endpoint: endpoint, + cacheBuster: defaultCacheBuster, + getWeek: defaultWeekGenerator, + } +} + +// Builds endpoint url based on adapter-specific pub settings from imp.ext +func (a *YieldlabAdapter) makeEndpointURL(req *openrtb.BidRequest, params *openrtb_ext.ExtImpYieldlab) (string, error) { + uri, err := url.Parse(a.endpoint) + if err != nil { + return "", fmt.Errorf("failed to parse yieldlab endpoint: %v", err) + } + + uri.Path = path.Join(uri.Path, params.AdslotID) + q := uri.Query() + q.Set("content", "json") + q.Set("pvid", "true") + q.Set("ts", a.cacheBuster()) + q.Set("t", a.makeTargetingValues(params)) + + if req.User != nil && req.User.BuyerUID != "" { + q.Set("ids", "ylid:"+req.User.BuyerUID) + } + + if req.Device != nil { + q.Set("yl_rtb_ifa", req.Device.IFA) + q.Set("yl_rtb_devicetype", fmt.Sprintf("%v", req.Device.DeviceType)) + + if req.Device.ConnectionType != nil { + q.Set("yl_rtb_connectiontype", fmt.Sprintf("%v", req.Device.ConnectionType.Val())) + } + + if req.Device.Geo != nil { + q.Set("lat", fmt.Sprintf("%v", req.Device.Geo.Lat)) + q.Set("lon", fmt.Sprintf("%v", req.Device.Geo.Lon)) + } + } + + if req.App != nil { + q.Set("pubappname", req.App.Name) + q.Set("pubbundlename", req.App.Bundle) + } + + gdpr, consent, err := a.getGDPR(req) + if err != nil { + return "", err + } + if gdpr != "" && consent != "" { + q.Set("gdpr", gdpr) + q.Set("consent", consent) + } + + uri.RawQuery = q.Encode() + + return uri.String(), nil +} + +func (a *YieldlabAdapter) getGDPR(request *openrtb.BidRequest) (string, string, error) { + gdpr := "" + var extRegs openrtb_ext.ExtRegs + if request.Regs != nil { + if err := json.Unmarshal(request.Regs.Ext, &extRegs); err != nil { + return "", "", fmt.Errorf("failed to parse ExtRegs in Yieldlab GDPR check: %v", err) + } + if extRegs.GDPR != nil && (*extRegs.GDPR == 0 || *extRegs.GDPR == 1) { + gdpr = strconv.Itoa(int(*extRegs.GDPR)) + } + } + + consent := "" + if request.User != nil && request.User.Ext != nil { + var extUser openrtb_ext.ExtUser + if err := json.Unmarshal(request.User.Ext, &extUser); err != nil { + return "", "", fmt.Errorf("failed to parse ExtUser in Yieldlab GDPR check: %v", err) + } + consent = extUser.Consent + } + + return gdpr, consent, nil +} + +func (a *YieldlabAdapter) makeTargetingValues(params *openrtb_ext.ExtImpYieldlab) string { + values := url.Values{} + for k, v := range params.Targeting { + values.Set(k, v) + } + return values.Encode() +} + +func (a *YieldlabAdapter) MakeRequests(request *openrtb.BidRequest, _ *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + if len(request.Imp) == 0 { + return nil, []error{fmt.Errorf("invalid request %+v, no Impressions given", request)} + } + + bidURL, err := a.makeEndpointURL(request, a.mergeParams(a.parseRequest(request))) + if err != nil { + return nil, []error{err} + } + + headers := http.Header{} + headers.Add("Accept", "application/json") + if request.Site != nil { + headers.Add("Referer", request.Site.Page) + } + if request.Device != nil { + headers.Add("User-Agent", request.Device.UA) + headers.Add("X-Forwarded-For", request.Device.IP) + } + if request.User != nil { + headers.Add("Cookie", "id="+request.User.BuyerUID) + } + + return []*adapters.RequestData{{ + Method: "GET", + Uri: bidURL, + Headers: headers, + }}, nil +} + +// parseRequest extracts the Yieldlab request information from the request +func (a *YieldlabAdapter) parseRequest(request *openrtb.BidRequest) []*openrtb_ext.ExtImpYieldlab { + params := make([]*openrtb_ext.ExtImpYieldlab, 0) + + for i := 0; i < len(request.Imp); i++ { + bidderExt := new(adapters.ExtImpBidder) + if err := json.Unmarshal(request.Imp[i].Ext, bidderExt); err != nil { + continue + } + + yieldlabExt := new(openrtb_ext.ExtImpYieldlab) + if err := json.Unmarshal(bidderExt.Bidder, yieldlabExt); err != nil { + continue + } + + params = append(params, yieldlabExt) + } + + return params +} + +func (a *YieldlabAdapter) mergeParams(params []*openrtb_ext.ExtImpYieldlab) *openrtb_ext.ExtImpYieldlab { + var adSlotIds []string + targeting := make(map[string]string) + + for _, p := range params { + adSlotIds = append(adSlotIds, p.AdslotID) + for k, v := range p.Targeting { + targeting[k] = v + } + } + + return &openrtb_ext.ExtImpYieldlab{ + AdslotID: strings.Join(adSlotIds, adSlotIdSeparator), + Targeting: targeting, + } +} + +// MakeBids make the bids for the bid response. +func (a *YieldlabAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if response.StatusCode != 200 { + return nil, []error{ + &errortypes.BadServerResponse{ + Message: fmt.Sprintf("failed to resolve bids from yieldlab response: Unexpected response code %v", response.StatusCode), + }, + } + } + + bids := make([]*bidResponse, 0) + if err := json.Unmarshal(response.Body, &bids); err != nil { + return nil, []error{ + &errortypes.BadServerResponse{ + Message: fmt.Sprintf("failed to parse bids response from yieldlab: %v", err), + }, + } + } + + params := a.parseRequest(internalRequest) + + bidderResponse := &adapters.BidderResponse{ + Currency: currency.EUR.String(), + Bids: []*adapters.TypedBid{}, + } + + for i, bid := range bids { + width, height, err := splitSize(bid.Adsize) + if err != nil { + return nil, []error{err} + } + + req := a.findBidReq(bid.ID, params) + if req == nil { + return nil, []error{ + fmt.Errorf("failed to find yieldlab request for adslotID %v. This is most likely a programming issue", bid.ID), + } + } + + var bidType openrtb_ext.BidType + responseBid := &openrtb.Bid{ + ID: strconv.FormatUint(bid.ID, 10), + Price: float64(bid.Price) / 100, + ImpID: internalRequest.Imp[i].ID, + CrID: a.makeCreativeID(req, bid), + DealID: strconv.FormatUint(bid.Pid, 10), + W: width, + H: height, + } + + if internalRequest.Imp[i].Video != nil { + bidType = openrtb_ext.BidTypeVideo + responseBid.NURL = a.makeAdSourceURL(internalRequest, req, bid) + + } else if internalRequest.Imp[i].Banner != nil { + bidType = openrtb_ext.BidTypeBanner + responseBid.AdM = a.makeBannerAdSource(internalRequest, req, bid) + } else { + // Yieldlab adapter currently doesn't support Audio and Native ads + continue + } + + bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{ + BidType: bidType, + Bid: responseBid, + }) + } + + return bidderResponse, nil +} + +func (a *YieldlabAdapter) findBidReq(adslotID uint64, params []*openrtb_ext.ExtImpYieldlab) *openrtb_ext.ExtImpYieldlab { + slotIdStr := strconv.FormatUint(adslotID, 10) + for _, p := range params { + if p.AdslotID == slotIdStr { + return p + } + } + + return nil +} + +func (a *YieldlabAdapter) makeBannerAdSource(req *openrtb.BidRequest, ext *openrtb_ext.ExtImpYieldlab, res *bidResponse) string { + return fmt.Sprintf(adSourceBanner, a.makeAdSourceURL(req, ext, res)) +} + +func (a *YieldlabAdapter) makeAdSourceURL(req *openrtb.BidRequest, ext *openrtb_ext.ExtImpYieldlab, res *bidResponse) string { + val := url.Values{} + val.Set("ts", a.cacheBuster()) + val.Set("id", ext.ExtId) + val.Set("pvid", res.Pvid) + + if req.User != nil { + val.Set("ids", "ylid:"+req.User.BuyerUID) + } + + gdpr, consent, err := a.getGDPR(req) + if err == nil && gdpr != "" && consent != "" { + val.Set("gdpr", gdpr) + val.Set("consent", consent) + } + + return fmt.Sprintf(adSourceURL, ext.AdslotID, ext.SupplyID, res.Adsize, val.Encode()) +} + +func (a *YieldlabAdapter) makeCreativeID(req *openrtb_ext.ExtImpYieldlab, bid *bidResponse) string { + return fmt.Sprintf(creativeID, req.AdslotID, bid.Pid, a.getWeek()) +} + +func splitSize(size string) (uint64, uint64, error) { + sizeParts := strings.Split(size, adsizeSeparator) + if len(sizeParts) != 2 { + return 0, 0, nil + } + + width, err := strconv.ParseUint(sizeParts[0], 10, 64) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse yieldlab adsize: %v", err) + } + + height, err := strconv.ParseUint(sizeParts[1], 10, 64) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse yieldlab adsize: %v", err) + } + + return width, height, nil + +} diff --git a/adapters/yieldlab/yieldlab_test.go b/adapters/yieldlab/yieldlab_test.go new file mode 100644 index 00000000000..b6ca0507ab8 --- /dev/null +++ b/adapters/yieldlab/yieldlab_test.go @@ -0,0 +1,128 @@ +package yieldlab + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/prebid/prebid-server/adapters/adapterstest" +) + +const testURL = "https://ad.yieldlab.net/testing/" + +var testCacheBuster cacheBuster = func() string { + return "testing" +} + +var testWeekGenerator weekGenerator = func() string { + return "33" +} + +func newTestYieldlabBidder(endpoint string) *YieldlabAdapter { + return &YieldlabAdapter{ + endpoint: endpoint, + cacheBuster: testCacheBuster, + getWeek: testWeekGenerator, + } +} + +func TestNewYieldlabBidder(t *testing.T) { + bid := NewYieldlabBidder(testURL) + assert.NotNil(t, bid) + assert.Equal(t, bid.endpoint, testURL) + assert.NotNil(t, bid.cacheBuster) + assert.NotNil(t, bid.getWeek) +} + +func TestJsonSamples(t *testing.T) { + adapterstest.RunJSONBidderTest(t, "yieldlabtest", newTestYieldlabBidder(testURL)) +} + +func Test_splitSize(t *testing.T) { + type args struct { + size string + } + tests := []struct { + name string + args args + want uint64 + want1 uint64 + wantErr bool + }{ + { + name: "valid", + args: args{ + size: "300x800", + }, + want: 300, + want1: 800, + wantErr: false, + }, + { + name: "empty", + args: args{ + size: "", + }, + want: 0, + want1: 0, + wantErr: false, + }, + { + name: "invalid", + args: args{ + size: "test", + }, + want: 0, + want1: 0, + wantErr: false, + }, + { + name: "invalid_height", + args: args{ + size: "200xtest", + }, + want: 0, + want1: 0, + wantErr: true, + }, + { + name: "invalid_width", + args: args{ + size: "testx200", + }, + want: 0, + want1: 0, + wantErr: true, + }, + { + name: "invalid_separator", + args: args{ + size: "200y200", + }, + want: 0, + want1: 0, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1, err := splitSize(tt.args.size) + if (err != nil) != tt.wantErr { + t.Errorf("splitSize() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("splitSize() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("splitSize() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func TestYieldlabAdapter_makeEndpointURL_invalidEndpoint(t *testing.T) { + bid := NewYieldlabBidder("test$:/somethingĀ§") + _, err := bid.makeEndpointURL(nil, nil) + assert.Error(t, err) +} diff --git a/adapters/yieldlab/yieldlabtest/exemplary/banner.json b/adapters/yieldlab/yieldlabtest/exemplary/banner.json new file mode 100644 index 00000000000..8dd94404097 --- /dev/null +++ b/adapters/yieldlab/yieldlabtest/exemplary/banner.json @@ -0,0 +1,111 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "adslotId": "12345", + "supplyId": "123456789", + "adSize": "728x90", + "targeting": { + "key1": "value1", + "key2": "value2" + }, + "extId": "abc" + } + } + } + ], + "user": { + "buyeruid": "34a53e82-0dc3-4815-8b7e-b725ede0361c" + }, + "device": { + "ifa": "hello-ads", + "devicetype": 4, + "connectiontype": 6, + "geo": { + "lat": 51.499488, + "lon": -0.128953 + }, + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36", + "ip": "169.254.13.37", + "h": 1098, + "w": 814 + }, + "site": { + "id": "fake-site-id", + "publisher": { + "id": "1" + }, + "page": "http://localhost:9090/gdpr.html" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Cookie": [ + "id=34a53e82-0dc3-4815-8b7e-b725ede0361c" + ], + "Referer": [ + "http://localhost:9090/gdpr.html" + ], + "User-Agent": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" + ], + "X-Forwarded-For": [ + "169.254.13.37" + ] + }, + "uri": "https://ad.yieldlab.net/testing/12345?content=json&ids=ylid%3A34a53e82-0dc3-4815-8b7e-b725ede0361c&lat=51.499488&lon=-0.128953&pvid=true&t=key1%3Dvalue1%26key2%3Dvalue2&ts=testing&yl_rtb_connectiontype=6&yl_rtb_devicetype=4&yl_rtb_ifa=hello-ads" + }, + "mockResponse": { + "status": 200, + "body": [ + { + "id": 12345, + "price": 201, + "advertiser": "yieldlab", + "adsize": "728x90", + "pid": 1234, + "did": 5678, + "pvid": "40cb3251-1e1e-4cfd-8edc-7d32dc1a21e5" + } + ] + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "adm": "", + "crid": "12345123433", + "dealid": "1234", + "id": "12345", + "impid": "test-imp-id", + "price": 2.01, + "w": 728, + "h": 90 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/yieldlab/yieldlabtest/exemplary/gdpr.json b/adapters/yieldlab/yieldlabtest/exemplary/gdpr.json new file mode 100644 index 00000000000..381ba688e09 --- /dev/null +++ b/adapters/yieldlab/yieldlabtest/exemplary/gdpr.json @@ -0,0 +1,119 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "adslotId": "12345", + "supplyId": "123456789", + "adSize": "728x90", + "targeting": { + "key1": "value1", + "key2": "value2" + }, + "extId": "abc" + } + } + } + ], + "device": { + "ifa": "hello-ads", + "devicetype": 4, + "connectiontype": 6, + "geo": { + "lat": 51.499488, + "lon": -0.128953 + }, + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36", + "ip": "169.254.13.37", + "h": 1098, + "w": 814 + }, + "regs": { + "ext": { + "gdpr": 1 + } + }, + "site": { + "id": "fake-site-id", + "publisher": { + "id": "1" + }, + "page": "http://localhost:9090/gdpr.html" + }, + "user": { + "buyeruid": "34a53e82-0dc3-4815-8b7e-b725ede0361c", + "ext": { + "consent": "BOlOrv1OlOr2EAAABADECg-AAAApp7v______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-3zd4u_1vf99yfm1-7etr3tp_87ues2_Xur__79__3z3_9phP78k89r7337Ew-v02" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Cookie": [ + "id=34a53e82-0dc3-4815-8b7e-b725ede0361c" + ], + "Referer": [ + "http://localhost:9090/gdpr.html" + ], + "User-Agent": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" + ], + "X-Forwarded-For": [ + "169.254.13.37" + ] + }, + "uri": "https://ad.yieldlab.net/testing/12345?consent=BOlOrv1OlOr2EAAABADECg-AAAApp7v______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-3zd4u_1vf99yfm1-7etr3tp_87ues2_Xur__79__3z3_9phP78k89r7337Ew-v02&content=json&gdpr=1&ids=ylid%3A34a53e82-0dc3-4815-8b7e-b725ede0361c&lat=51.499488&lon=-0.128953&pvid=true&t=key1%3Dvalue1%26key2%3Dvalue2&ts=testing&yl_rtb_connectiontype=6&yl_rtb_devicetype=4&yl_rtb_ifa=hello-ads" + }, + "mockResponse": { + "status": 200, + "body": [ + { + "id": 12345, + "price": 201, + "advertiser": "yieldlab", + "adsize": "728x90", + "pid": 1234, + "did": 5678, + "pvid": "40cb3251-1e1e-4cfd-8edc-7d32dc1a21e5" + } + ] + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "adm": "", + "crid": "12345123433", + "dealid": "1234", + "id": "12345", + "impid": "test-imp-id", + "price": 2.01, + "w": 728, + "h": 90 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/yieldlab/yieldlabtest/exemplary/video.json b/adapters/yieldlab/yieldlabtest/exemplary/video.json new file mode 100644 index 00000000000..9e970ae79b5 --- /dev/null +++ b/adapters/yieldlab/yieldlabtest/exemplary/video.json @@ -0,0 +1,136 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "adslotId": "12345", + "supplyId": "123456789", + "adSize": "728x90", + "targeting": { + "key1": "value1", + "key2": "value2" + }, + "extId": "abc" + } + }, + "video": { + "context": "instream", + "mimes": [ + "video/mp4" + ], + "playerSize": [ + [ + 400, + 600 + ] + ], + "minduration": 1, + "maxduration": 2, + "protocols": [ + 1, + 2 + ], + "w": 1, + "h": 2, + "startdelay": 1, + "placement": 1, + "playbackmethod": [ + 2 + ] + } + } + ], + "user": { + "buyeruid": "34a53e82-0dc3-4815-8b7e-b725ede0361c" + }, + "device": { + "ifa": "hello-ads", + "devicetype": 4, + "connectiontype": 6, + "geo": { + "lat": 51.499488, + "lon": -0.128953 + }, + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36", + "ip": "169.254.13.37", + "h": 1098, + "w": 814 + }, + "site": { + "id": "fake-site-id", + "publisher": { + "id": "1" + }, + "page": "http://localhost:9090/gdpr.html" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Cookie": [ + "id=34a53e82-0dc3-4815-8b7e-b725ede0361c" + ], + "Referer": [ + "http://localhost:9090/gdpr.html" + ], + "User-Agent": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" + ], + "X-Forwarded-For": [ + "169.254.13.37" + ] + }, + "uri": "https://ad.yieldlab.net/testing/12345?content=json&ids=ylid%3A34a53e82-0dc3-4815-8b7e-b725ede0361c&lat=51.499488&lon=-0.128953&pvid=true&t=key1%3Dvalue1%26key2%3Dvalue2&ts=testing&yl_rtb_connectiontype=6&yl_rtb_devicetype=4&yl_rtb_ifa=hello-ads" + }, + "mockResponse": { + "status": 200, + "body": [ + { + "id": 12345, + "price": 201, + "advertiser": "yieldlab", + "adsize": "728x90", + "pid": 1234, + "did": 5678, + "pvid": "40cb3251-1e1e-4cfd-8edc-7d32dc1a21e5" + } + ] + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "crid": "12345123433", + "dealid": "1234", + "id": "12345", + "impid": "test-imp-id", + "nurl": "https://ad.yieldlab.net/d/12345/123456789/728x90?id=abc&ids=ylid%3A34a53e82-0dc3-4815-8b7e-b725ede0361c&pvid=40cb3251-1e1e-4cfd-8edc-7d32dc1a21e5&ts=testing", + "price": 2.01, + "w": 728, + "h": 90 + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/yieldlab/yieldlabtest/exemplary/video_app.json b/adapters/yieldlab/yieldlabtest/exemplary/video_app.json new file mode 100644 index 00000000000..67d526b3400 --- /dev/null +++ b/adapters/yieldlab/yieldlabtest/exemplary/video_app.json @@ -0,0 +1,136 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "adslotId": "12345", + "supplyId": "123456789", + "adSize": "728x90", + "targeting": { + "key1": "value1", + "key2": "value2" + }, + "extId": "abc" + } + }, + "video": { + "context": "instream", + "mimes": [ + "video/mp4" + ], + "playerSize": [ + [ + 400, + 600 + ] + ], + "minduration": 1, + "maxduration": 2, + "protocols": [ + 1, + 2 + ], + "w": 1, + "h": 2, + "startdelay": 1, + "placement": 1, + "playbackmethod": [ + 2 + ] + } + } + ], + "user": { + "buyeruid": "34a53e82-0dc3-4815-8b7e-b725ede0361c" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789" + }, + "device": { + "ifa": "hello-ads", + "devicetype": 4, + "connectiontype": 6, + "geo": { + "lat": 51.499488, + "lon": -0.128953 + }, + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36", + "ip": "169.254.13.37", + "h": 1098, + "w": 814 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Cookie": [ + "id=34a53e82-0dc3-4815-8b7e-b725ede0361c" + ], + "User-Agent": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" + ], + "X-Forwarded-For": [ + "169.254.13.37" + ] + }, + "uri": "https://ad.yieldlab.net/testing/12345?content=json&ids=ylid%3A34a53e82-0dc3-4815-8b7e-b725ede0361c&lat=51.499488&lon=-0.128953&pubappname=Awesome+App&pubbundlename=com.app.awesome&pvid=true&t=key1%3Dvalue1%26key2%3Dvalue2&ts=testing&yl_rtb_connectiontype=6&yl_rtb_devicetype=4&yl_rtb_ifa=hello-ads" + }, + "mockResponse": { + "status": 200, + "body": [ + { + "id": 12345, + "price": 201, + "advertiser": "yieldlab", + "adsize": "728x90", + "pid": 1234, + "did": 5678, + "pvid": "40cb3251-1e1e-4cfd-8edc-7d32dc1a21e5" + } + ] + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "crid": "12345123433", + "dealid": "1234", + "id": "12345", + "impid": "test-imp-id", + "nurl": "https://ad.yieldlab.net/d/12345/123456789/728x90?id=abc&ids=ylid%3A34a53e82-0dc3-4815-8b7e-b725ede0361c&pvid=40cb3251-1e1e-4cfd-8edc-7d32dc1a21e5&ts=testing", + "price": 2.01, + "w": 728, + "h": 90 + }, + "type": "video" + } + ] + } + ] +} diff --git a/config/config.go b/config/config.go index 5c66f4cdf02..86f2e9a98a0 100755 --- a/config/config.go +++ b/config/config.go @@ -551,6 +551,7 @@ func (cfg *Configuration) setDerivedDefaults() { setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderValueImpression, "https://rtb.valueimpression.com/usersync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvalueimpression%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}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dvisx%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D") // openrtb_ext.BidderVrtcal doesn't have a good default. + setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldlab, "https://ad.yieldlab.net/mr?t=2&pid=9140838&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldlab%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25YL_UID%25%25") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldmo, "https://ads.yieldmo.com/pbsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldmo%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderYieldone, "https://y.one.impact-ad.jp/hbs_sc?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirectUri="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dyieldone%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID") setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderZeroClickFraud, "https://s.0cf.io/sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dzeroclickfraud%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D") @@ -760,6 +761,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.visx.endpoint", "https://t.visx.net/s2s_bid?wrapperType=s2s_prebid_standard") v.SetDefault("adapters.vrtcal.endpoint", "http://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804") v.SetDefault("adapters.yeahmobi.endpoint", "https://{{.Host}}/prebid/bid") + v.SetDefault("adapters.yieldlab.endpoint", "https://ad.yieldlab.net/yp/") v.SetDefault("adapters.yieldmo.endpoint", "https://ads.yieldmo.com/exchange/prebid-server") v.SetDefault("adapters.yieldone.endpoint", "https://y.one.impact-ad.jp/hbs_imp") v.SetDefault("adapters.zeroclickfraud.endpoint", "http://{{.Host}}/openrtb2?sid={{.SourceId}}") diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go index b91f01a7e9a..b69b5b50e13 100755 --- a/exchange/adapter_map.go +++ b/exchange/adapter_map.go @@ -73,6 +73,7 @@ import ( "github.com/prebid/prebid-server/adapters/visx" "github.com/prebid/prebid-server/adapters/vrtcal" "github.com/prebid/prebid-server/adapters/yeahmobi" + "github.com/prebid/prebid-server/adapters/yieldlab" "github.com/prebid/prebid-server/adapters/yieldmo" "github.com/prebid/prebid-server/adapters/yieldone" "github.com/prebid/prebid-server/adapters/zeroclickfraud" @@ -153,6 +154,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter openrtb_ext.BidderUcfunnel: ucfunnel.NewUcfunnelBidder(cfg.Adapters[string(openrtb_ext.BidderUcfunnel)].Endpoint), openrtb_ext.BidderUnruly: unruly.NewUnrulyBidder(client, cfg.Adapters[string(openrtb_ext.BidderUnruly)].Endpoint), openrtb_ext.BidderValueImpression: valueimpression.NewValueImpressionBidder(cfg.Adapters[string(openrtb_ext.BidderValueImpression)].Endpoint), + openrtb_ext.BidderYieldlab: yieldlab.NewYieldlabBidder(cfg.Adapters[string(openrtb_ext.BidderYieldlab)].Endpoint), openrtb_ext.BidderVerizonMedia: verizonmedia.NewVerizonMediaBidder(client, cfg.Adapters[string(openrtb_ext.BidderVerizonMedia)].Endpoint), openrtb_ext.BidderVisx: visx.NewVisxBidder(cfg.Adapters[string(openrtb_ext.BidderVisx)].Endpoint), openrtb_ext.BidderVrtcal: vrtcal.NewVrtcalBidder(cfg.Adapters[string(openrtb_ext.BidderVrtcal)].Endpoint), diff --git a/go.mod b/go.mod index 89cc69e4519..8de6f10e4b9 100644 --- a/go.mod +++ b/go.mod @@ -7,23 +7,17 @@ require ( github.com/DATA-DOG/go-sqlmock v1.3.0 github.com/NYTimes/gziphandler v1.1.1 github.com/OneOfOne/xxhash v1.2.5 // indirect - github.com/aerospike/aerospike-client-go v2.7.2+incompatible github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect github.com/blang/semver v3.5.1+incompatible - github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 github.com/cespare/xxhash v1.0.0 // indirect github.com/chasex/glog v0.0.0-20160217080310-c62392af379c github.com/coocood/freecache v1.0.1 - github.com/didip/tollbooth v4.0.2+incompatible github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 github.com/evanphx/json-patch v0.0.0-20180720181644-f195058310bd - github.com/go-redis/redis v6.15.7+incompatible - github.com/gocql/gocql v0.0.0-20200203083758-81b8263d9fe5 github.com/gofrs/uuid v3.2.0+incompatible github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/golang/snappy v0.0.1 github.com/hashicorp/hcl v1.0.0 // indirect github.com/influxdata/influxdb v1.6.1 // indirect github.com/julienschmidt/httprouter v1.1.0 @@ -37,10 +31,8 @@ require ( github.com/mxmCherry/openrtb v11.0.0+incompatible github.com/onsi/ginkgo v1.10.1 // indirect github.com/onsi/gomega v1.7.0 // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/prebid/go-gdpr v0.7.0 - github.com/prebid/prebid-cache v0.0.0-20200218152159-6d6d678c1caf github.com/prometheus/client_golang v0.0.0-20180623155954-77e8f2ddcfed github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect @@ -48,27 +40,24 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 github.com/rs/cors v1.5.0 github.com/sergi/go-diff v1.0.0 // indirect - github.com/sirupsen/logrus v1.4.2 github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.1.1 // indirect github.com/spf13/cast v1.2.0 // indirect github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834 // indirect github.com/spf13/pflag v1.0.2 // indirect github.com/spf13/viper v1.1.0 + github.com/stretchr/objx v0.1.1 // indirect github.com/stretchr/testify v1.5.1 - github.com/valyala/fasthttp v1.9.0 github.com/vrischmann/go-metrics-influxdb v0.0.0-20160917065939-43af8332c303 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v0.0.0-20180816142147-da425ebb7609 - github.com/xorcare/pointer v1.1.0 github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yudai/pp v2.0.1+incompatible // indirect - github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect + golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect golang.org/x/text v0.3.0 - golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index f929408f0f3..176bacfc20a 100644 --- a/go.sum +++ b/go.sum @@ -6,57 +6,35 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/aerospike/aerospike-client-go v2.7.2+incompatible h1:bWbRf8trg1FhKF7u43KLGNfOH60RlvIgQjpaS107DZ8= -github.com/aerospike/aerospike-client-go v2.7.2+incompatible/go.mod h1:zj8LBEnWBDOVEIJt8LvaRvDG5ARAoa5dBeHaB472NRc= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0= -github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 h1:y853v6rXx+zefEcjET3JuKAqvhj+FKflQijjeaSv2iA= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cespare/xxhash v1.0.0 h1:naDmySfoNg0nKS62/ujM6e71ZgM2AoVdaqGwMG0w18A= github.com/cespare/xxhash v1.0.0/go.mod h1:fX/lfQBkSCDXZSUgv6jVIu/EVA3/JNseAX5asI4c4T4= github.com/chasex/glog v0.0.0-20160217080310-c62392af379c h1:eXqCBUHfmjbeDqcuvzjsd+bM6A+bnwo5N9FVbV6m5/s= github.com/chasex/glog v0.0.0-20160217080310-c62392af379c/go.mod h1:omJZNg0Qu76bxJd+ExohVo8uXzNcGOk2bv7vel460xk= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/coocood/freecache v1.0.1 h1:oFyo4msX2c0QIKU+kuMJUwsKamJ+AKc2JJrKcMszJ5M= github.com/coocood/freecache v1.0.1/go.mod h1:ePwxCDzOYvARfHdr1pByNct1at3CoKnsipOHwKlNbzI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/didip/tollbooth v4.0.2+incompatible h1:fVSa33JzSz0hoh2NxpwZtksAzAgd7zjmGO20HCZtF4M= -github.com/didip/tollbooth v4.0.2+incompatible/go.mod h1:A9b0665CE6l1KmzpDws2++elm/CsuWBMa5Jv4WY0PEY= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v0.0.0-20180720181644-f195058310bd h1:biTJQdqouE5by89AAffXG8++TY+9Fsdrg5rinbt3tHk= github.com/evanphx/json-patch v0.0.0-20180720181644-f195058310bd/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U= -github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/gocql/gocql v0.0.0-20200203083758-81b8263d9fe5 h1:ZZVxQRCm4ewuoqqLBJ7LHpsk4OGx2PkyCsRKLq4oHgE= -github.com/gocql/gocql v0.0.0-20200203083758-81b8263d9fe5/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -67,17 +45,6 @@ github.com/julienschmidt/httprouter v1.1.0 h1:7wLdtIiIpzOkC9u6sXOozpBauPdskj3ru4 github.com/julienschmidt/httprouter v1.1.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= @@ -99,16 +66,12 @@ github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prebid/go-gdpr v0.7.0 h1:m4E/FjUhTBMciDsd3lQlbzFyXLzNK+JQkFmInJpFAwc= github.com/prebid/go-gdpr v0.7.0/go.mod h1:FPY0uxSrl9/Mz237LnPo3ge4aCG0wQ9FWf2b4WhwNn0= -github.com/prebid/prebid-cache v0.0.0-20200218152159-6d6d678c1caf h1:CcE+KN1tCtWKsUFH5IzdQxHIgP609VSIVe5Hywg2phs= -github.com/prebid/prebid-cache v0.0.0-20200218152159-6d6d678c1caf/go.mod h1:k5xrl5ZpnumN1S2x8w8cMiFYsgRuVyAeFJz+BkSi+98= github.com/prometheus/client_golang v0.0.0-20180623155954-77e8f2ddcfed h1:0dloFFFNNDG7c+8qtkYw2FdADrWy9s5cI8wHp6tK3Mg= github.com/prometheus/client_golang v0.0.0-20180623155954-77e8f2ddcfed/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= @@ -123,8 +86,6 @@ github.com/rs/cors v1.5.0 h1:dgSHE6+ia18arGOTIYQKKGWLvEbGvmbNE6NfxhoNHUY= github.com/rs/cors v1.5.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.1 h1:Lt3ihYMlE+lreX1GS4Qw4ZsNpYQLxIXKBTEOXm3nt6I= @@ -140,16 +101,10 @@ github.com/spf13/viper v1.1.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7Sr github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.9.0 h1:hNpmUdy/+ZXYpGy0OBfm7K0UQTzb73W0T0U4iJIVrMw= -github.com/valyala/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vrischmann/go-metrics-influxdb v0.0.0-20160917065939-43af8332c303 h1:Va10CytCCYRm4xBTses5ZDeDjeIQjhaiC9nRCe/yflI= github.com/vrischmann/go-metrics-influxdb v0.0.0-20160917065939-43af8332c303/go.mod h1:Xdcad1nGVhQfhoV0go+/4WaI/RZkWlvfjkVCdpMTxPY= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= @@ -158,16 +113,12 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180816142147-da425ebb7609 h1:BcMExZAULPkihVZ7UJXK7t8rwGqisXFw75tILnafhBY= github.com/xeipuuv/gojsonschema v0.0.0-20180816142147-da425ebb7609/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xorcare/pointer v1.1.0 h1:sFwXOhRF8QZ0tyVZrtxWGIoVZNEmRzBCaFWdONPQIUM= -github.com/xorcare/pointer v1.1.0/go.mod h1:6KLhkOh6YbuvZkT4YbxIbR/wzLBjyMxOiNzZhJTor2Y= github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d h1:yJIizrfO599ot2kQ6Af1enICnwBD3XoxgX3MrMwot2M= github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= -github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0= -github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -178,7 +129,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -186,14 +136,10 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/p golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index f2f8e7c67ab..8a53e4adcf2 100755 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -91,6 +91,7 @@ const ( BidderVisx BidderName = "visx" BidderVrtcal BidderName = "vrtcal" BidderYeahmobi BidderName = "yeahmobi" + BidderYieldlab BidderName = "yieldlab" BidderYieldmo BidderName = "yieldmo" BidderYieldone BidderName = "yieldone" BidderZeroClickFraud BidderName = "zeroclickfraud" @@ -166,6 +167,7 @@ var BidderMap = map[string]BidderName{ "visx": BidderVisx, "vrtcal": BidderVrtcal, "yeahmobi": BidderYeahmobi, + "yieldlab": BidderYieldlab, "yieldmo": BidderYieldmo, "yieldone": BidderYieldone, "zeroclickfraud": BidderZeroClickFraud, diff --git a/openrtb_ext/imp_yieldlab.go b/openrtb_ext/imp_yieldlab.go new file mode 100644 index 00000000000..604b7e8ceab --- /dev/null +++ b/openrtb_ext/imp_yieldlab.go @@ -0,0 +1,10 @@ +package openrtb_ext + +// ExtImpYieldlab defines the contract for bidrequest.imp[i].ext.yieldlab +type ExtImpYieldlab struct { + AdslotID string `json:"adslotId"` + SupplyID string `json:"supplyId"` + AdSize string `json:"adSize"` + Targeting map[string]string `json:"targeting"` + ExtId string `json:"extId"` +} diff --git a/static/bidder-info/yieldlab.yaml b/static/bidder-info/yieldlab.yaml new file mode 100644 index 00000000000..654e6c749cb --- /dev/null +++ b/static/bidder-info/yieldlab.yaml @@ -0,0 +1,11 @@ +maintainer: + email: "solutions@yieldlab.de" +capabilities: + site: + mediaTypes: + - banner + - video + app: + mediaTypes: + - banner + - video diff --git a/static/bidder-params/yieldlab.json b/static/bidder-params/yieldlab.json new file mode 100644 index 00000000000..900d65da6e5 --- /dev/null +++ b/static/bidder-params/yieldlab.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Yieldlab Adapter Params", + "description": "A schema which validates params accepted by the Yieldlab adapter", + "type": "object", + "properties": { + "adslotId": { + "type": "string", + "description": "Yieldlab ID of the ad slot" + }, + "supplyId": { + "type": "string", + "description": "Yieldlab ID of the supply" + }, + "adSize": { + "type": "string", + "description": "Size of the adslot in pixel, e.g. 200x50" + }, + "extId": { + "type": "string", + "description": "External ID used for reporting" + }, + "targeting": { + "type": "object", + "description": "Targeting information in key value pairs" + } + }, + "required": [ + "adslotId", + "supplyId", + "adSize" + ] +} diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go index 3f12ee7f728..791a00de0a9 100755 --- a/usersync/usersyncers/syncer.go +++ b/usersync/usersyncers/syncer.go @@ -61,6 +61,7 @@ import ( "github.com/prebid/prebid-server/adapters/verizonmedia" "github.com/prebid/prebid-server/adapters/visx" "github.com/prebid/prebid-server/adapters/vrtcal" + "github.com/prebid/prebid-server/adapters/yieldlab" "github.com/prebid/prebid-server/adapters/yieldmo" "github.com/prebid/prebid-server/adapters/yieldone" "github.com/prebid/prebid-server/adapters/zeroclickfraud" @@ -131,6 +132,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync insertIntoMap(cfg, syncers, openrtb_ext.BidderVerizonMedia, verizonmedia.NewVerizonMediaSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderVisx, visx.NewVisxSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderVrtcal, vrtcal.NewVrtcalSyncer) + insertIntoMap(cfg, syncers, openrtb_ext.BidderYieldlab, yieldlab.NewYieldlabSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderYieldmo, yieldmo.NewYieldmoSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderYieldone, yieldone.NewYieldoneSyncer) insertIntoMap(cfg, syncers, openrtb_ext.BidderZeroClickFraud, zeroclickfraud.NewZeroClickFraudSyncer) diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go index 20fce80c83a..9aae284da2a 100755 --- a/usersync/usersyncers/syncer_test.go +++ b/usersync/usersyncers/syncer_test.go @@ -67,6 +67,7 @@ func TestNewSyncerMap(t *testing.T) { string(openrtb_ext.BidderUcfunnel): syncConfig, string(openrtb_ext.BidderUnruly): syncConfig, string(openrtb_ext.BidderValueImpression): syncConfig, + string(openrtb_ext.BidderYieldlab): syncConfig, string(openrtb_ext.BidderVerizonMedia): syncConfig, string(openrtb_ext.BidderVisx): syncConfig, string(openrtb_ext.BidderVrtcal): syncConfig,