From 3021a1f53496eb7d27e8a73a8da524c56671b89c Mon Sep 17 00:00:00 2001 From: andreasmaurer0210 <62548508+andreasmaurer0210@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:29:00 +0100 Subject: [PATCH 01/14] Orbidder: bidfloor currency handling (#2093) --- adapters/orbidder/orbidder.go | 66 ++++---- adapters/orbidder/orbidder_test.go | 147 ++++++++++++++++++ .../exemplary/simple-app-banner.json | 1 + .../supplemental/dsp-bad-request-example.json | 1 + .../dsp-bad-response-example.json | 1 + .../dsp-internal-server-error-example.json | 1 + .../dsp-invalid-accountid-example.json | 1 + .../supplemental/empty-imp-request-error.json | 19 --- .../supplemental/no-content-response.json | 1 + .../supplemental/valid-and-invalid-imps.json | 1 + 10 files changed, 194 insertions(+), 45 deletions(-) delete mode 100644 adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json diff --git a/adapters/orbidder/orbidder.go b/adapters/orbidder/orbidder.go index 77985c8dae0..f2dda85e290 100644 --- a/adapters/orbidder/orbidder.go +++ b/adapters/orbidder/orbidder.go @@ -3,13 +3,13 @@ package orbidder import ( "encoding/json" "fmt" - "net/http" - "github.com/mxmCherry/openrtb/v15/openrtb2" "github.com/prebid/prebid-server/adapters" "github.com/prebid/prebid-server/config" "github.com/prebid/prebid-server/errortypes" "github.com/prebid/prebid-server/openrtb_ext" + "net/http" + "strings" ) type OrbidderAdapter struct { @@ -18,30 +18,11 @@ type OrbidderAdapter struct { // MakeRequests makes the HTTP requests which should be made to fetch bids from orbidder. func (rcv *OrbidderAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - var errs []error - var validImps []openrtb2.Imp - - // check if imps exists, if not return error and do send request to orbidder. - if len(request.Imp) == 0 { - return nil, []error{&errortypes.BadInput{ - Message: "No impressions in request", - }} - } - - // validate imps - for _, imp := range request.Imp { - if err := preprocess(&imp); err != nil { - errs = append(errs, err) - continue - } - validImps = append(validImps, imp) - } - + validImps, errs := getValidImpressions(request, reqInfo) if len(validImps) == 0 { return nil, errs } - //set imp array to only valid imps request.Imp = validImps requestBodyJSON, err := json.Marshal(request) @@ -55,14 +36,34 @@ func (rcv *OrbidderAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo * headers.Add("Accept", "application/json") return []*adapters.RequestData{{ - Method: "POST", + Method: http.MethodPost, Uri: rcv.endpoint, Body: requestBodyJSON, Headers: headers, }}, errs } -func preprocess(imp *openrtb2.Imp) error { +// getValidImpressions validate imps and check for bid floor currency. Convert to EUR if necessary +func getValidImpressions(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]openrtb2.Imp, []error) { + var errs []error + var validImps []openrtb2.Imp + + for _, imp := range request.Imp { + if err := preprocessBidFloorCurrency(&imp, reqInfo); err != nil { + errs = append(errs, err) + continue + } + + if err := preprocessExtensions(&imp); err != nil { + errs = append(errs, err) + continue + } + validImps = append(validImps, imp) + } + return validImps, errs +} + +func preprocessExtensions(imp *openrtb2.Imp) error { var bidderExt adapters.ExtImpBidder if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { return &errortypes.BadInput{ @@ -80,8 +81,21 @@ func preprocess(imp *openrtb2.Imp) error { return nil } +func preprocessBidFloorCurrency(imp *openrtb2.Imp, reqInfo *adapters.ExtraRequestInfo) error { + // we expect every currency related data to be EUR + if imp.BidFloor > 0 && strings.ToUpper(imp.BidFloorCur) != "EUR" && imp.BidFloorCur != "" { + if convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "EUR"); err != nil { + return err + } else { + imp.BidFloor = convertedValue + } + } + imp.BidFloorCur = "EUR" + return nil +} + // MakeBids unpacks server response into Bids. -func (rcv OrbidderAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { +func (rcv OrbidderAdapter) MakeBids(_ *openrtb2.BidRequest, _ *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { if response.StatusCode == http.StatusNoContent { return nil, nil } @@ -125,7 +139,7 @@ func (rcv OrbidderAdapter) MakeBids(internalRequest *openrtb2.BidRequest, extern } // Builder builds a new instance of the Orbidder adapter for the given bidder with the given config. -func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { +func Builder(_ openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { bidder := &OrbidderAdapter{ endpoint: config.Endpoint, } diff --git a/adapters/orbidder/orbidder_test.go b/adapters/orbidder/orbidder_test.go index 0eaed23a971..bbda1c06223 100644 --- a/adapters/orbidder/orbidder_test.go +++ b/adapters/orbidder/orbidder_test.go @@ -2,6 +2,10 @@ package orbidder import ( "encoding/json" + "errors" + "github.com/mxmCherry/openrtb/v15/openrtb2" + "github.com/prebid/prebid-server/adapters" + "github.com/stretchr/testify/mock" "testing" "github.com/prebid/prebid-server/adapters/adapterstest" @@ -22,6 +26,16 @@ func TestUnmarshalOrbidderExtImp(t *testing.T) { }, impExt) } +func TestPreprocessExtensions(t *testing.T) { + for name, tc := range testCasesExtension { + t.Run(name, func(t *testing.T) { + imp := tc.imp + err := preprocessExtensions(&imp) + tc.assertError(t, err) + }) + } +} + func TestJsonSamples(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.BidderOrbidder, config.Adapter{ Endpoint: "https://orbidder-test"}) @@ -32,3 +46,136 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "orbiddertest", bidder) } + +var testCasesCurrency = map[string]struct { + imp openrtb2.Imp + setMock func(m *mock.Mock) + expectedImp openrtb2.Imp + assertError func(t assert.TestingT, err error, msgAndArgs ...interface{}) bool +}{ + "EUR: no bidfloor, no currency": { + imp: openrtb2.Imp{ + BidFloor: 0, + BidFloorCur: "", + }, + setMock: func(m *mock.Mock) {}, + expectedImp: openrtb2.Imp{ + BidFloor: 0, + BidFloorCur: "EUR", + }, + assertError: assert.NoError, + }, + "EUR: bidfloor, no currency": { + imp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "", + }, + setMock: func(m *mock.Mock) {}, + expectedImp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "EUR", + }, + assertError: assert.NoError, + }, + "EUR: bidfloor and currency": { + imp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "EUR", + }, + setMock: func(m *mock.Mock) {}, + expectedImp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "EUR", + }, + assertError: assert.NoError, + }, + "USD: bidfloor with currency": { + imp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "USD", + }, + setMock: func(m *mock.Mock) { + m.On("GetRate", "USD", "EUR").Return(2.5, nil) + }, + expectedImp: openrtb2.Imp{ + BidFloor: 2.5, + BidFloorCur: "EUR", + }, + assertError: assert.NoError, + }, + "USD: no bidfloor": { + imp: openrtb2.Imp{ + BidFloor: 0, + BidFloorCur: "USD", + }, + setMock: func(m *mock.Mock) {}, + expectedImp: openrtb2.Imp{ + BidFloor: 0, + BidFloorCur: "EUR", + }, + assertError: assert.NoError, + }, + "ABC: invalid currency code": { + imp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "ABC", + }, + setMock: func(m *mock.Mock) { + m.On("GetRate", "ABC", "EUR").Return(0.0, errors.New("currency conversion error")) + }, + expectedImp: openrtb2.Imp{ + BidFloor: 1, + BidFloorCur: "ABC", + }, + assertError: assert.Error, + }, +} + +var testCasesExtension = map[string]struct { + imp openrtb2.Imp + assertError func(t assert.TestingT, err error, msgAndArgs ...interface{}) bool +}{ + "Valid Orbidder Extension": { + imp: openrtb2.Imp{ + Ext: json.RawMessage(`{"bidder":{"accountId":"orbidder-test", "placementId":"center-banner", "bidfloor": 0.1}}`), + }, + assertError: assert.NoError, + }, + "Invalid Orbidder Extension": { + imp: openrtb2.Imp{ + Ext: json.RawMessage(`{"there's'":{"something":"strange", "in the":"neighbourhood", "who you gonna call?": 0.1}}`), + }, + assertError: assert.Error, + }, +} + +func TestPreprocessBidFloorCurrency(t *testing.T) { + for name, tc := range testCasesCurrency { + t.Run(name, func(t *testing.T) { + imp := tc.imp + mockConversions := &mockCurrencyConversion{} + tc.setMock(&mockConversions.Mock) + extraRequestInfo := adapters.ExtraRequestInfo{ + CurrencyConversions: mockConversions, + } + err := preprocessBidFloorCurrency(&imp, &extraRequestInfo) + assert.True(t, mockConversions.AssertExpectations(t)) + tc.assertError(t, err) + assert.Equal(t, tc.expectedImp, imp) + }) + } +} + +type mockCurrencyConversion struct { + mock.Mock +} + +func (m *mockCurrencyConversion) GetRate(from string, to string) (float64, error) { + args := m.Called(from, to) + return args.Get(0).(float64), args.Error(1) +} + +func (m *mockCurrencyConversion) GetRates() *map[string]map[string]float64 { + args := m.Called() + return args.Get(0).(*map[string]map[string]float64) +} diff --git a/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json b/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json index 8697bff3a92..2315a52c130 100644 --- a/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json +++ b/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json @@ -51,6 +51,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json index 69496c4ff3f..dc199d24ead 100644 --- a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json +++ b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json @@ -51,6 +51,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json index d1c57a54a9e..61e70d315f7 100644 --- a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json +++ b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json @@ -51,6 +51,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json index 20ea36ab38c..66a766a9261 100644 --- a/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json +++ b/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json @@ -51,6 +51,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json index 6bc0482dd0c..7944db44bce 100644 --- a/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json +++ b/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json @@ -51,6 +51,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", diff --git a/adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json b/adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json deleted file mode 100644 index 0c5cf6d2faa..00000000000 --- a/adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "mockBidRequest": { - "id": "test-request-id", - "imp": [ - ], - "app": { - "bundle": "com.prebid" - }, - "device": { - "ifa":"87857b31-8942-4646-ae80-ab9c95bf3fab" - } - }, - "expectedMakeRequestsErrors": [ - { - "value": "No impressions in request", - "comparison": "literal" - } - ] -} diff --git a/adapters/orbidder/orbiddertest/supplemental/no-content-response.json b/adapters/orbidder/orbiddertest/supplemental/no-content-response.json index f3b1b287da7..0a1e5f0fc4d 100644 --- a/adapters/orbidder/orbiddertest/supplemental/no-content-response.json +++ b/adapters/orbidder/orbiddertest/supplemental/no-content-response.json @@ -51,6 +51,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", diff --git a/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json b/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json index b6db9f48ee3..1ea133ab1d3 100644 --- a/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json +++ b/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json @@ -57,6 +57,7 @@ } ] }, + "bidfloorcur": "EUR", "ext": { "bidder": { "accountId": "orbidder-test", From d4d25d1e58df46a87cdf1ae36a6365879f96379e Mon Sep 17 00:00:00 2001 From: CompassSSP <95415988+CompassSSP@users.noreply.github.com> Date: Mon, 20 Dec 2021 20:31:01 +0200 Subject: [PATCH 02/14] New Adapter: Compass (#2102) --- adapters/compass/compass.go | 154 ++++++++++++++++++ adapters/compass/compass_test.go | 20 +++ .../compasstest/exemplary/endpointId.json | 133 +++++++++++++++ .../compasstest/exemplary/simple-banner.json | 133 +++++++++++++++ .../compasstest/exemplary/simple-native.json | 117 +++++++++++++ .../compasstest/exemplary/simple-video.json | 128 +++++++++++++++ .../exemplary/simple-web-banner.json | 133 +++++++++++++++ .../supplemental/bad_media_type.json | 86 ++++++++++ .../supplemental/bad_response.json | 84 ++++++++++ .../compasstest/supplemental/status-204.json | 79 +++++++++ .../supplemental/status-not-200.json | 84 ++++++++++ adapters/compass/params_test.go | 47 ++++++ config/config.go | 1 + exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_compass.go | 6 + static/bidder-info/compass.yaml | 19 +++ static/bidder-params/compass.json | 23 +++ 18 files changed, 1251 insertions(+) create mode 100644 adapters/compass/compass.go create mode 100644 adapters/compass/compass_test.go create mode 100644 adapters/compass/compasstest/exemplary/endpointId.json create mode 100644 adapters/compass/compasstest/exemplary/simple-banner.json create mode 100644 adapters/compass/compasstest/exemplary/simple-native.json create mode 100644 adapters/compass/compasstest/exemplary/simple-video.json create mode 100644 adapters/compass/compasstest/exemplary/simple-web-banner.json create mode 100644 adapters/compass/compasstest/supplemental/bad_media_type.json create mode 100644 adapters/compass/compasstest/supplemental/bad_response.json create mode 100644 adapters/compass/compasstest/supplemental/status-204.json create mode 100644 adapters/compass/compasstest/supplemental/status-not-200.json create mode 100644 adapters/compass/params_test.go create mode 100644 openrtb_ext/imp_compass.go create mode 100644 static/bidder-info/compass.yaml create mode 100644 static/bidder-params/compass.json diff --git a/adapters/compass/compass.go b/adapters/compass/compass.go new file mode 100644 index 00000000000..eed846576bb --- /dev/null +++ b/adapters/compass/compass.go @@ -0,0 +1,154 @@ +package compass + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/mxmCherry/openrtb/v15/openrtb2" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/config" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" +) + +type adapter struct { + endpoint string +} + +type reqBodyExt struct { + CompassBidderExt reqBodyExtBidder `json:"bidder"` +} + +type reqBodyExtBidder struct { + Type string `json:"type"` + PlacementID string `json:"placementId,omitempty"` + EndpointID string `json:"endpointId,omitempty"` +} + +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var err error + var adapterRequests []*adapters.RequestData + + reqCopy := *request + for _, imp := range request.Imp { + reqCopy.Imp = []openrtb2.Imp{imp} + + var bidderExt adapters.ExtImpBidder + var compassExt openrtb_ext.ImpExtCompass + + if err = json.Unmarshal(reqCopy.Imp[0].Ext, &bidderExt); err != nil { + return nil, []error{err} + } + if err = json.Unmarshal(bidderExt.Bidder, &compassExt); err != nil { + return nil, []error{err} + } + + temp := reqBodyExt{CompassBidderExt: reqBodyExtBidder{}} + + if compassExt.PlacementID != "" { + temp.CompassBidderExt.PlacementID = compassExt.PlacementID + temp.CompassBidderExt.Type = "publisher" + } else if compassExt.EndpointID != "" { + temp.CompassBidderExt.EndpointID = compassExt.EndpointID + temp.CompassBidderExt.Type = "network" + } + + finalyImpExt, err := json.Marshal(temp) + if err != nil { + return nil, []error{err} + } + + reqCopy.Imp[0].Ext = finalyImpExt + + adapterReq, err := a.makeRequest(&reqCopy) + if err != nil { + return nil, []error{err} + } + + if adapterReq != nil { + adapterRequests = append(adapterRequests, adapterReq) + } + } + return adapterRequests, nil +} + +func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) { + reqJSON, err := json.Marshal(request) + if err != nil { + return nil, err + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + return &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: reqJSON, + Headers: headers, + }, err +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if responseData.StatusCode == http.StatusNoContent { + return nil, nil + } + + if responseData.StatusCode != http.StatusOK { + err := &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), + } + return nil, []error{err} + } + + var response openrtb2.BidResponse + if err := json.Unmarshal(responseData.Body, &response); err != nil { + return nil, []error{err} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + bidResponse.Currency = response.Cur + for _, seatBid := range response.SeatBid { + for i := range seatBid.Bid { + bidType, err := getMediaTypeForImp(seatBid.Bid[i].ImpID, request.Imp) + if err != nil { + return nil, []error{err} + } + + b := &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + } + bidResponse.Bids = append(bidResponse.Bids, b) + } + } + return bidResponse, nil +} + +func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) { + for _, imp := range imps { + if imp.ID == impID { + if imp.Banner != nil { + return openrtb_ext.BidTypeBanner, nil + } + if imp.Video != nil { + return openrtb_ext.BidTypeVideo, nil + } + if imp.Native != nil { + return openrtb_ext.BidTypeNative, nil + } + } + } + + return "", &errortypes.BadInput{ + Message: fmt.Sprintf("Failed to find impression \"%s\"", impID), + } +} diff --git a/adapters/compass/compass_test.go b/adapters/compass/compass_test.go new file mode 100644 index 00000000000..fce791e5997 --- /dev/null +++ b/adapters/compass/compass_test.go @@ -0,0 +1,20 @@ +package compass + +import ( + "testing" + + "github.com/prebid/prebid-server/adapters/adapterstest" + "github.com/prebid/prebid-server/config" + "github.com/prebid/prebid-server/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderCompass, config.Adapter{ + Endpoint: "http://sa-lb.deliverimp.com/pserver"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "compasstest", bidder) +} diff --git a/adapters/compass/compasstest/exemplary/endpointId.json b/adapters/compass/compasstest/exemplary/endpointId.json new file mode 100644 index 00000000000..f02481b32a3 --- /dev/null +++ b/adapters/compass/compasstest/exemplary/endpointId.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "endpointId": "test" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "endpointId": "test", + "type": "network" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "compass" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/compass/compasstest/exemplary/simple-banner.json b/adapters/compass/compasstest/exemplary/simple-banner.json new file mode 100644 index 00000000000..592570cda6b --- /dev/null +++ b/adapters/compass/compasstest/exemplary/simple-banner.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "compass" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/compass/compasstest/exemplary/simple-native.json b/adapters/compass/compasstest/exemplary/simple-native.json new file mode 100644 index 00000000000..0ec8b43ce9c --- /dev/null +++ b/adapters/compass/compasstest/exemplary/simple-native.json @@ -0,0 +1,117 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "native": { + "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "native": { + "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "native" + } + } + } + ], + "seat": "compass" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "native" + } + } + }, + "type": "native" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/compass/compasstest/exemplary/simple-video.json b/adapters/compass/compasstest/exemplary/simple-video.json new file mode 100644 index 00000000000..0f279496f36 --- /dev/null +++ b/adapters/compass/compasstest/exemplary/simple-video.json @@ -0,0 +1,128 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 1024, + "h": 576 + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "video": { + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, + 5 + ], + "w": 1024, + "h": 576 + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "00:01:00", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "ext": { + "prebid": { + "type": "video" + } + } + } + ], + "seat": "compass" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "00:01:00", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "ext": { + "prebid": { + "type": "video" + } + } + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/compass/compasstest/exemplary/simple-web-banner.json b/adapters/compass/compasstest/exemplary/simple-web-banner.json new file mode 100644 index 00000000000..1896101ac68 --- /dev/null +++ b/adapters/compass/compasstest/exemplary/simple-web-banner.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ], + "site": { + "id": "1", + "domain": "test.com" + }, + "device": { + "ip": "123.123.123.123", + "ua": "Ubuntu" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "site": { + "id": "1", + "domain": "test.com" + }, + "device": { + "ip": "123.123.123.123", + "ua": "Ubuntu" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 468, + "h": 60, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "compass" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 468, + "h": 60, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/compass/compasstest/supplemental/bad_media_type.json b/adapters/compass/compasstest/supplemental/bad_media_type.json new file mode 100644 index 00000000000..0bfaec4f23d --- /dev/null +++ b/adapters/compass/compasstest/supplemental/bad_media_type.json @@ -0,0 +1,86 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "compass" + } + ], + "cur": "USD" + } + } + }], + "expectedMakeBidsErrors": [ + { + "value": "Failed to find impression \"test-imp-id\"", + "comparison": "literal" + } + ] +} diff --git a/adapters/compass/compasstest/supplemental/bad_response.json b/adapters/compass/compasstest/supplemental/bad_response.json new file mode 100644 index 00000000000..3c660338c63 --- /dev/null +++ b/adapters/compass/compasstest/supplemental/bad_response.json @@ -0,0 +1,84 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 200, + "body": "" + } + }], + "expectedMakeBidsErrors": [ + { + "value": "json: cannot unmarshal string into Go value of type openrtb2.BidResponse", + "comparison": "literal" + } + ] +} diff --git a/adapters/compass/compasstest/supplemental/status-204.json b/adapters/compass/compasstest/supplemental/status-204.json new file mode 100644 index 00000000000..1ff5c55abeb --- /dev/null +++ b/adapters/compass/compasstest/supplemental/status-204.json @@ -0,0 +1,79 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 204, + "body": {} + } + }], + "expectedBidResponses": [] +} diff --git a/adapters/compass/compasstest/supplemental/status-not-200.json b/adapters/compass/compasstest/supplemental/status-not-200.json new file mode 100644 index 00000000000..51f648de360 --- /dev/null +++ b/adapters/compass/compasstest/supplemental/status-not-200.json @@ -0,0 +1,84 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + }, + "httpCalls": [{ + "expectedRequest": { + "uri": "http://sa-lb.deliverimp.com/pserver", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": "test", + "type": "publisher" + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.wls.testwlsapplication" + }, + "device": { + "ip": "123.123.123.123", + "ifa": "sdjfksdf-dfsds-dsdg-dsgg" + } + } + }, + "mockResponse": { + "status": 404, + "body": {} + } + }], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 404. Run with request.debug = 1 for more info.", + "comparison": "literal" + } + ] +} diff --git a/adapters/compass/params_test.go b/adapters/compass/params_test.go new file mode 100644 index 00000000000..fca398b06fb --- /dev/null +++ b/adapters/compass/params_test.go @@ -0,0 +1,47 @@ +package compass + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/openrtb_ext" +) + +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json schema. %v", err) + } + + for _, p := range validParams { + if err := validator.Validate(openrtb_ext.BidderCompass, json.RawMessage(p)); err != nil { + t.Errorf("Schema rejected valid params: %s", p) + } + } +} + +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json schema. %v", err) + } + + for _, p := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderCompass, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + } +} + +var validParams = []string{ + `{"placementId": "test"}`, + `{"placementId": "1"}`, + `{"endpointId": "test"}`, + `{"endpointId": "1"}`, +} + +var invalidParams = []string{ + `{"placementId": 42}`, + `{"endpointId": 42}`, + `{"placementId": "1", "endpointId": "1"}`, +} diff --git a/config/config.go b/config/config.go index f9dbc274ec1..dd842be72b9 100644 --- a/config/config.go +++ b/config/config.go @@ -809,6 +809,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.brightroll.endpoint", "http://east-bid.ybp.yahoo.com/bid/appnexuspbs") v.SetDefault("adapters.coinzilla.endpoint", "http://request-global.czilladx.com/serve/prebid-server.php") v.SetDefault("adapters.colossus.endpoint", "http://colossusssp.com/?c=o&m=rtb") + v.SetDefault("adapters.compass.endpoint", "http://sa-lb.deliverimp.com/pserver") v.SetDefault("adapters.connectad.endpoint", "http://bidder.connectad.io/API?src=pbs") v.SetDefault("adapters.consumable.endpoint", "https://e.serverbid.com/api/v2") v.SetDefault("adapters.conversant.endpoint", "http://api.hb.ad.cpe.dotomi.com/cvx/server/hb/ortb/25") diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 0f14b75c27f..59c892ab9e4 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -44,6 +44,7 @@ import ( "github.com/prebid/prebid-server/adapters/brightroll" "github.com/prebid/prebid-server/adapters/coinzilla" "github.com/prebid/prebid-server/adapters/colossus" + "github.com/prebid/prebid-server/adapters/compass" "github.com/prebid/prebid-server/adapters/connectad" "github.com/prebid/prebid-server/adapters/consumable" "github.com/prebid/prebid-server/adapters/conversant" @@ -183,6 +184,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderBrightroll: brightroll.Builder, openrtb_ext.BidderCoinzilla: coinzilla.Builder, openrtb_ext.BidderColossus: colossus.Builder, + openrtb_ext.BidderCompass: compass.Builder, openrtb_ext.BidderConnectAd: connectad.Builder, openrtb_ext.BidderConsumable: consumable.Builder, openrtb_ext.BidderConversant: conversant.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 7ebfe631bdb..d02a7a48320 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -119,6 +119,7 @@ const ( BidderBrightroll BidderName = "brightroll" BidderCoinzilla BidderName = "coinzilla" BidderColossus BidderName = "colossus" + BidderCompass BidderName = "compass" BidderConnectAd BidderName = "connectad" BidderConsumable BidderName = "consumable" BidderConversant BidderName = "conversant" @@ -262,6 +263,7 @@ func CoreBidderNames() []BidderName { BidderBrightroll, BidderCoinzilla, BidderColossus, + BidderCompass, BidderConnectAd, BidderConsumable, BidderConversant, diff --git a/openrtb_ext/imp_compass.go b/openrtb_ext/imp_compass.go new file mode 100644 index 00000000000..3a150b9daaf --- /dev/null +++ b/openrtb_ext/imp_compass.go @@ -0,0 +1,6 @@ +package openrtb_ext + +type ImpExtCompass struct { + PlacementID string `json:"placementId"` + EndpointID string `json:"endpointId"` +} diff --git a/static/bidder-info/compass.yaml b/static/bidder-info/compass.yaml new file mode 100644 index 00000000000..5944b27eb5a --- /dev/null +++ b/static/bidder-info/compass.yaml @@ -0,0 +1,19 @@ +maintainer: + email: "sa-support@brightcom.com" +gvlVendorID: 883 +capabilities: + site: + mediaTypes: + - banner + - video + - native + + app: + mediaTypes: + - banner + - video + - native +userSync: + redirect: + url: "https://sa-cs.deliverimp.com/pserver?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}" + userMacro: "[UID]" diff --git a/static/bidder-params/compass.json b/static/bidder-params/compass.json new file mode 100644 index 00000000000..11fcbf31ea4 --- /dev/null +++ b/static/bidder-params/compass.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Compass Adapter Params", + "description": "A schema which validates params accepted by the Compass adapter", + "type": "object", + + "properties": { + "placementId": { + "type": "string", + "minLength": 1, + "description": "Placement ID" + }, + "endpointId": { + "type": "string", + "minLength": 1, + "description": "Endpoint ID" + } + }, + "oneOf": [ + { "required": ["placementId"] }, + { "required": ["endpointId"] } + ] + } \ No newline at end of file From 61ece3521f3c3b6838896633f7b5a7b6747b0cee Mon Sep 17 00:00:00 2001 From: thuyhq <61451682+thuyhq@users.noreply.github.com> Date: Tue, 21 Dec 2021 02:08:49 +0700 Subject: [PATCH 03/14] New Adapter: apacdex and Remove Adapter: valueimpression (#2097) Valueimpression to become apacdex adapter --- adapters/apacdex/apacdex.go | 161 ++++++++++++++++++ .../apacdex_test.go} | 6 +- .../exemplary/banner-and-video.json | 16 +- .../apacdextest}/exemplary/banner.json | 17 +- .../apacdextest}/exemplary/video.json | 0 .../supplemental/explicit-dimensions.json | 0 .../invalid-response-no-bids.json | 0 .../invalid-response-unmarshall-error.json | 0 .../supplemental/no-imps-in-request.json | 0 .../supplemental/server-error-code.json | 2 +- .../supplemental/server-no-content.json | 0 .../supplemental/wrong-bid-ext.json} | 12 +- .../supplemental/wrong-impression-ext.json | 2 +- .../params_test.go | 22 ++- adapters/valueimpression/valueimpression.go | 157 ----------------- config/config.go | 4 +- exchange/adapter_builders.go | 6 +- openrtb_ext/bidders.go | 4 + openrtb_ext/imp_apacdex.go | 7 + openrtb_ext/imp_valueimpression.go | 5 - static/bidder-info/apacdex.yaml | 20 +++ static/bidder-info/quantumdex.yaml | 20 +++ static/bidder-info/valueimpression.yaml | 11 +- static/bidder-params/apacdex.json | 32 ++++ static/bidder-params/quantumdex.json | 32 ++++ static/bidder-params/valueimpression.json | 43 +++-- 26 files changed, 371 insertions(+), 208 deletions(-) create mode 100644 adapters/apacdex/apacdex.go rename adapters/{valueimpression/valueimpression_test.go => apacdex/apacdex_test.go} (65%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/exemplary/banner-and-video.json (88%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/exemplary/banner.json (85%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/exemplary/video.json (100%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/explicit-dimensions.json (100%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/invalid-response-no-bids.json (100%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/invalid-response-unmarshall-error.json (100%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/no-imps-in-request.json (100%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/server-error-code.json (91%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/server-no-content.json (100%) rename adapters/{valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json => apacdex/apacdextest/supplemental/wrong-bid-ext.json} (85%) rename adapters/{valueimpression/valueimpressiontest => apacdex/apacdextest}/supplemental/wrong-impression-ext.json (89%) rename adapters/{valueimpression => apacdex}/params_test.go (53%) delete mode 100644 adapters/valueimpression/valueimpression.go create mode 100644 openrtb_ext/imp_apacdex.go delete mode 100644 openrtb_ext/imp_valueimpression.go create mode 100644 static/bidder-info/apacdex.yaml create mode 100644 static/bidder-info/quantumdex.yaml create mode 100644 static/bidder-params/apacdex.json create mode 100644 static/bidder-params/quantumdex.json diff --git a/adapters/apacdex/apacdex.go b/adapters/apacdex/apacdex.go new file mode 100644 index 00000000000..294b7188940 --- /dev/null +++ b/adapters/apacdex/apacdex.go @@ -0,0 +1,161 @@ +package apacdex + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/mxmCherry/openrtb/v15/openrtb2" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/config" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/openrtb_ext" +) + +type adapter struct { + endpoint string +} + +// Builder builds a new instance of the Apacdex adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var errs []error + var adapterRequests []*adapters.RequestData + + if err := preprocess(request); err != nil { + errs = append(errs, err) + return nil, errs + } + + adapterReq, err := a.makeRequest(request) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + adapterRequests = append(adapterRequests, adapterReq) + + return adapterRequests, errs +} + +func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) { + var err error + + jsonBody, err := json.Marshal(request) + if err != nil { + return nil, err + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + headers.Add("x-openrtb-version", "2.5") + + return &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: jsonBody, + Headers: headers, + }, nil +} + +func preprocess(request *openrtb2.BidRequest) error { + if len(request.Imp) == 0 { + return &errortypes.BadInput{ + Message: "No Imps in Bid Request", + } + } + for i := 0; i < len(request.Imp); i++ { + var imp = &request.Imp[i] + var bidderExt adapters.ExtImpBidder + + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + return &errortypes.BadInput{ + Message: err.Error(), + } + } + + var extImp openrtb_ext.ExtImpApacdex + if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil { + return &errortypes.BadInput{ + Message: err.Error(), + } + } + + imp.Ext = bidderExt.Bidder + } + + return nil +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if responseData.StatusCode == http.StatusNoContent { + return nil, nil + } + + if responseData.StatusCode == http.StatusBadRequest { + err := &errortypes.BadInput{ + Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + } + return nil, []error{err} + } + + if responseData.StatusCode != http.StatusOK { + err := &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode), + } + return nil, []error{err} + } + + var response openrtb2.BidResponse + + if err := json.Unmarshal(responseData.Body, &response); err != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: err.Error(), + }} + } + + if len(response.SeatBid) == 0 { + return nil, nil + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + bidResponse.Currency = response.Cur + var errors []error + + for _, seatbid := range response.SeatBid { + for _, bid := range seatbid.Bid { + bidType, err := getMediaTypeForBid(bid) + if err != nil { + errors = append(errors, err) + continue + } + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + }) + } + } + return bidResponse, errors +} + +// getMediaTypeForBid determines which type of bid. +func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + if bid.Ext != nil { + var bidExt openrtb_ext.ExtBid + err := json.Unmarshal(bid.Ext, &bidExt) + if err == nil && bidExt.Prebid != nil { + return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) + } + } + + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to parse bid mediatype for impression \"%s\"", bid.ImpID), + } +} diff --git a/adapters/valueimpression/valueimpression_test.go b/adapters/apacdex/apacdex_test.go similarity index 65% rename from adapters/valueimpression/valueimpression_test.go rename to adapters/apacdex/apacdex_test.go index f4d33864978..997302f6ea4 100644 --- a/adapters/valueimpression/valueimpression_test.go +++ b/adapters/apacdex/apacdex_test.go @@ -1,4 +1,4 @@ -package valueimpression +package apacdex import ( "testing" @@ -9,12 +9,12 @@ import ( ) func TestJsonSamples(t *testing.T) { - bidder, buildErr := Builder(openrtb_ext.BidderValueImpression, config.Adapter{ + bidder, buildErr := Builder(openrtb_ext.BidderApacdex, config.Adapter{ Endpoint: "//host"}) if buildErr != nil { t.Fatalf("Builder returned unexpected error %v", buildErr) } - adapterstest.RunJSONBidderTest(t, "valueimpressiontest", bidder) + adapterstest.RunJSONBidderTest(t, "apacdextest", bidder) } diff --git a/adapters/valueimpression/valueimpressiontest/exemplary/banner-and-video.json b/adapters/apacdex/apacdextest/exemplary/banner-and-video.json similarity index 88% rename from adapters/valueimpression/valueimpressiontest/exemplary/banner-and-video.json rename to adapters/apacdex/apacdextest/exemplary/banner-and-video.json index fd9d401cd44..78ce13fd106 100644 --- a/adapters/valueimpression/valueimpressiontest/exemplary/banner-and-video.json +++ b/adapters/apacdex/apacdextest/exemplary/banner-and-video.json @@ -92,7 +92,7 @@ "id": "test-request-id", "seatbid": [ { - "seat": "valueimpression", + "seat": "apacdex", "bid": [ { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", @@ -101,7 +101,12 @@ "adm": "some-test-ad", "crid": "crid_10", "h": 250, - "w": 300 + "w": 300, + "ext": { + "prebid": { + "type": "video" + } + } } ] } @@ -121,7 +126,12 @@ "adm": "some-test-ad", "crid": "crid_10", "w": 300, - "h": 250 + "h": 250, + "ext": { + "prebid": { + "type": "video" + } + } }, "type": "video" } diff --git a/adapters/valueimpression/valueimpressiontest/exemplary/banner.json b/adapters/apacdex/apacdextest/exemplary/banner.json similarity index 85% rename from adapters/valueimpression/valueimpressiontest/exemplary/banner.json rename to adapters/apacdex/apacdextest/exemplary/banner.json index 1ef11ade199..31b685da15f 100644 --- a/adapters/valueimpression/valueimpressiontest/exemplary/banner.json +++ b/adapters/apacdex/apacdextest/exemplary/banner.json @@ -56,7 +56,7 @@ "id": "test-request-id", "seatbid": [ { - "seat": "valueimpression", + "seat": "apacdex", "bid": [ { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", @@ -65,7 +65,12 @@ "adm": "some-test-ad", "crid": "crid_10", "h": 250, - "w": 300 + "w": 300, + "ext": { + "prebid": { + "type": "banner" + } + } } ] } @@ -87,7 +92,12 @@ "adm": "some-test-ad", "crid": "crid_10", "w": 300, - "h": 250 + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } }, "type": "banner" } @@ -95,4 +105,3 @@ } ] } - \ No newline at end of file diff --git a/adapters/valueimpression/valueimpressiontest/exemplary/video.json b/adapters/apacdex/apacdextest/exemplary/video.json similarity index 100% rename from adapters/valueimpression/valueimpressiontest/exemplary/video.json rename to adapters/apacdex/apacdextest/exemplary/video.json diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/explicit-dimensions.json b/adapters/apacdex/apacdextest/supplemental/explicit-dimensions.json similarity index 100% rename from adapters/valueimpression/valueimpressiontest/supplemental/explicit-dimensions.json rename to adapters/apacdex/apacdextest/supplemental/explicit-dimensions.json diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-no-bids.json b/adapters/apacdex/apacdextest/supplemental/invalid-response-no-bids.json similarity index 100% rename from adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-no-bids.json rename to adapters/apacdex/apacdextest/supplemental/invalid-response-no-bids.json diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-unmarshall-error.json b/adapters/apacdex/apacdextest/supplemental/invalid-response-unmarshall-error.json similarity index 100% rename from adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-unmarshall-error.json rename to adapters/apacdex/apacdextest/supplemental/invalid-response-unmarshall-error.json diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/no-imps-in-request.json b/adapters/apacdex/apacdextest/supplemental/no-imps-in-request.json similarity index 100% rename from adapters/valueimpression/valueimpressiontest/supplemental/no-imps-in-request.json rename to adapters/apacdex/apacdextest/supplemental/no-imps-in-request.json diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/server-error-code.json b/adapters/apacdex/apacdextest/supplemental/server-error-code.json similarity index 91% rename from adapters/valueimpression/valueimpressiontest/supplemental/server-error-code.json rename to adapters/apacdex/apacdextest/supplemental/server-error-code.json index ea31fdc2fe9..b8656aa74a5 100644 --- a/adapters/valueimpression/valueimpressiontest/supplemental/server-error-code.json +++ b/adapters/apacdex/apacdextest/supplemental/server-error-code.json @@ -46,7 +46,7 @@ "expectedMakeBidsErrors": [ { - "value": "Bad server response: HTTP status 500", + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info.", "comparison": "literal" } ] diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/server-no-content.json b/adapters/apacdex/apacdextest/supplemental/server-no-content.json similarity index 100% rename from adapters/valueimpression/valueimpressiontest/supplemental/server-no-content.json rename to adapters/apacdex/apacdextest/supplemental/server-no-content.json diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json b/adapters/apacdex/apacdextest/supplemental/wrong-bid-ext.json similarity index 85% rename from adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json rename to adapters/apacdex/apacdextest/supplemental/wrong-bid-ext.json index ef4d3a7526b..f2842d88d2f 100644 --- a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json +++ b/adapters/apacdex/apacdextest/supplemental/wrong-bid-ext.json @@ -20,7 +20,6 @@ } ] }, - "httpCalls": [ { "expectedRequest": { @@ -29,7 +28,7 @@ "id": "test-request-id", "imp": [ { - "id":"test-imp-id", + "id": "test-imp-id", "video": { "w": 900, "h": 250, @@ -54,10 +53,11 @@ "bid": [ { "id": "test-bid-id", - "impid": "BOGUS-IMPID", + "impid": "another-imp-id", "price": 3.5, "w": 900, - "h": 250 + "h": 250, + "ext": {} } ] } @@ -68,8 +68,8 @@ ], "expectedMakeBidsErrors": [ { - "value": "bid id='test-bid-id' could not find valid impid='BOGUS-IMPID'", + "value": "Failed to parse bid mediatype for impression \"another-imp-id\"", "comparison": "regex" } -] + ] } \ No newline at end of file diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-ext.json b/adapters/apacdex/apacdextest/supplemental/wrong-impression-ext.json similarity index 89% rename from adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-ext.json rename to adapters/apacdex/apacdextest/supplemental/wrong-impression-ext.json index 13514ac8ab8..09efa59563d 100644 --- a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-ext.json +++ b/adapters/apacdex/apacdextest/supplemental/wrong-impression-ext.json @@ -19,7 +19,7 @@ "expectedMakeRequestsErrors": [ { - "value": "json: cannot unmarshal number into Go struct field ExtImpValueImpression.siteId of type string", + "value": "json: cannot unmarshal number into Go struct field ExtImpApacdex.siteId of type string", "comparison": "literal" } ] diff --git a/adapters/valueimpression/params_test.go b/adapters/apacdex/params_test.go similarity index 53% rename from adapters/valueimpression/params_test.go rename to adapters/apacdex/params_test.go index 46471de24bb..2e5f626e16d 100644 --- a/adapters/valueimpression/params_test.go +++ b/adapters/apacdex/params_test.go @@ -1,4 +1,4 @@ -package valueimpression +package apacdex import ( "encoding/json" @@ -7,9 +7,9 @@ import ( "github.com/prebid/prebid-server/openrtb_ext" ) -// This file actually intends to test static/bidder-params/valueimpression.json -// These also validate the format of the external API: request.imp[i].ext.valueimpression -// TestValidParams makes sure that the ValueImpression schema accepts all imp.ext fields which we intend to support. +// This file actually intends to test static/bidder-params/apacdex.json +// These also validate the format of the external API: request.imp[i].ext.apacdex +// TestValidParams makes sure that the Apacdex schema accepts all imp.ext fields which we intend to support. func TestValidParams(t *testing.T) { validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") @@ -18,13 +18,13 @@ func TestValidParams(t *testing.T) { } for _, validParam := range validParams { - if err := validator.Validate(openrtb_ext.BidderValueImpression, json.RawMessage(validParam)); err != nil { - t.Errorf("Schema rejected ValueImpression params: %s", validParam) + if err := validator.Validate(openrtb_ext.BidderApacdex, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected Apacdex params: %s", validParam) } } } -// TestInvalidParams makes sure that the ValueImpression schema rejects all the imp.ext fields we don't support. +// TestInvalidParams makes sure that the Apacdex 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 { @@ -32,7 +32,7 @@ func TestInvalidParams(t *testing.T) { } for _, invalidParam := range invalidParams { - if err := validator.Validate(openrtb_ext.BidderValueImpression, json.RawMessage(invalidParam)); err == nil { + if err := validator.Validate(openrtb_ext.BidderApacdex, json.RawMessage(invalidParam)); err == nil { t.Errorf("Schema allowed unexpected params: %s", invalidParam) } } @@ -40,6 +40,9 @@ func TestInvalidParams(t *testing.T) { var validParams = []string{ `{"siteId": "123"}`, + `{"siteId": "123", "floorPrice": 0.05}`, + `{"placementId": "123123"}`, + `{"placementId": "123123", "floorPrice": 0.05}`, } var invalidParams = []string{ @@ -47,6 +50,7 @@ var invalidParams = []string{ `null`, `true`, `154`, - `{"siteId": 123}`, // siteId should be string + `{"siteId": 123}`, `{"invalid_param": "123"}`, + `{"siteId": "123", "placementId": "123123"}`, } diff --git a/adapters/valueimpression/valueimpression.go b/adapters/valueimpression/valueimpression.go deleted file mode 100644 index aac8faab52c..00000000000 --- a/adapters/valueimpression/valueimpression.go +++ /dev/null @@ -1,157 +0,0 @@ -package valueimpression - -import ( - "encoding/json" - "fmt" - "net/http" - - "github.com/mxmCherry/openrtb/v15/openrtb2" - "github.com/prebid/prebid-server/adapters" - "github.com/prebid/prebid-server/config" - "github.com/prebid/prebid-server/errortypes" - "github.com/prebid/prebid-server/openrtb_ext" -) - -type ValueImpressionAdapter struct { - endpoint string -} - -func (a *ValueImpressionAdapter) MakeRequests(request *openrtb2.BidRequest, unused *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - var errs []error - var adapterRequests []*adapters.RequestData - - if err := preprocess(request); err != nil { - errs = append(errs, err) - return nil, errs - } - - adapterReq, err := a.makeRequest(request) - if err != nil { - errs = append(errs, err) - return nil, errs - } - - adapterRequests = append(adapterRequests, adapterReq) - - return adapterRequests, errs -} - -func (a *ValueImpressionAdapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) { - var err error - - jsonBody, err := json.Marshal(request) - if err != nil { - return nil, err - } - - headers := http.Header{} - headers.Add("Content-Type", "application/json;charset=utf-8") - - return &adapters.RequestData{ - Method: "POST", - Uri: a.endpoint, - Body: jsonBody, - Headers: headers, - }, nil -} - -func preprocess(request *openrtb2.BidRequest) error { - if len(request.Imp) == 0 { - return &errortypes.BadInput{ - Message: "No Imps in Bid Request", - } - } - for i := 0; i < len(request.Imp); i++ { - var imp = &request.Imp[i] - var bidderExt adapters.ExtImpBidder - - if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { - return &errortypes.BadInput{ - Message: err.Error(), - } - } - - var extImp openrtb_ext.ExtImpValueImpression - if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil { - return &errortypes.BadInput{ - Message: err.Error(), - } - } - - imp.Ext = bidderExt.Bidder - } - - return nil -} - -// MakeBids based on valueimpression server response -func (a *ValueImpressionAdapter) MakeBids(bidRequest *openrtb2.BidRequest, unused *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { - if responseData.StatusCode == http.StatusNoContent { - return nil, nil - } - - if responseData.StatusCode == http.StatusBadRequest { - return nil, []error{&errortypes.BadInput{ - Message: fmt.Sprintf("Bad user input: HTTP status %d", responseData.StatusCode), - }} - } - - if responseData.StatusCode != http.StatusOK { - return nil, []error{&errortypes.BadServerResponse{ - Message: fmt.Sprintf("Bad server response: HTTP status %d", responseData.StatusCode), - }} - } - - var bidResponse openrtb2.BidResponse - - if err := json.Unmarshal(responseData.Body, &bidResponse); err != nil { - return nil, []error{&errortypes.BadServerResponse{ - Message: err.Error(), - }} - } - - if len(bidResponse.SeatBid) == 0 { - return nil, nil - } - - rv := adapters.NewBidderResponseWithBidsCapacity(len(bidResponse.SeatBid[0].Bid)) - var errors []error - - for _, seatbid := range bidResponse.SeatBid { - for _, bid := range seatbid.Bid { - foundMatchingBid := false - bidType := openrtb_ext.BidTypeBanner - for _, imp := range bidRequest.Imp { - if imp.ID == bid.ImpID { - foundMatchingBid = true - if imp.Banner != nil { - bidType = openrtb_ext.BidTypeBanner - } else if imp.Video != nil { - bidType = openrtb_ext.BidTypeVideo - } - break - } - } - - if foundMatchingBid { - rv.Bids = append(rv.Bids, &adapters.TypedBid{ - Bid: &bid, - BidType: bidType, - }) - } else { - errors = append(errors, &errortypes.BadServerResponse{ - Message: fmt.Sprintf("bid id='%s' could not find valid impid='%s'", bid.ID, bid.ImpID), - }) - } - } - } - return rv, errors -} - -// Builder builds a new instance of the Valueimpression adapter for the given bidder with the given config. -func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { - bidder := &ValueImpressionAdapter{ - endpoint: config.Endpoint, - } - return bidder, nil -} diff --git a/config/config.go b/config/config.go index dd842be72b9..7c7f721ecbb 100644 --- a/config/config.go +++ b/config/config.go @@ -790,6 +790,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.aja.endpoint", "https://ad.as.amanad.adtdp.com/v1/bid/4") v.SetDefault("adapters.algorix.endpoint", "https://{{.Host}}.svr-algorix.com/rtb/sa?sid={{.SourceId}}&token={{.AccountID}}") v.SetDefault("adapters.amx.endpoint", "http://pbs.amxrtb.com/auction/openrtb") + v.SetDefault("adapters.apacdex.endpoint", "http://useast.quantumdex.io/auction/pbs") v.SetDefault("adapters.applogy.endpoint", "http://rtb.applogy.com/v1/prebid") v.SetDefault("adapters.appnexus.endpoint", "http://ib.adnxs.com/openrtb2") // Docs: https://wiki.appnexus.com/display/supply/Incoming+Bid+Request+from+SSPs v.SetDefault("adapters.appnexus.platform_id", "5") @@ -868,6 +869,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.pubmatic.endpoint", "https://hbopenbid.pubmatic.com/translator?source=prebid-server") v.SetDefault("adapters.pubnative.endpoint", "http://dsp.pubnative.net/bid/v1/request") v.SetDefault("adapters.pulsepoint.endpoint", "http://bid.contextweb.com/header/s/ortb/prebid-s2s") + v.SetDefault("adapters.quantumdex.endpoint", "http://useast.quantumdex.io/auction/pbs") v.SetDefault("adapters.revcontent.disabled", true) v.SetDefault("adapters.revcontent.endpoint", "https://trends.revcontent.com/rtb") v.SetDefault("adapters.rhythmone.endpoint", "http://tag.1rx.io/rmp") @@ -897,7 +899,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.ucfunnel.endpoint", "https://pbs.aralego.com/prebid") v.SetDefault("adapters.unicorn.endpoint", "https://ds.uncn.jp/pb/0/bid.json") v.SetDefault("adapters.unruly.endpoint", "https://targeting.unrulymedia.com/unruly_prebid_server") - v.SetDefault("adapters.valueimpression.endpoint", "https://rtb.valueimpression.com/endpoint") + v.SetDefault("adapters.valueimpression.endpoint", "http://useast.quantumdex.io/auction/pbs") v.SetDefault("adapters.verizonmedia.disabled", true) v.SetDefault("adapters.videobyte.endpoint", "https://x.videobyte.com/ortbhb") v.SetDefault("adapters.viewdeos.endpoint", "http://ghb.sync.viewdeos.com/pbs/ortb") diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 59c892ab9e4..8075b7f1ff5 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -28,6 +28,7 @@ import ( "github.com/prebid/prebid-server/adapters/aja" "github.com/prebid/prebid-server/adapters/algorix" "github.com/prebid/prebid-server/adapters/amx" + "github.com/prebid/prebid-server/adapters/apacdex" "github.com/prebid/prebid-server/adapters/applogy" "github.com/prebid/prebid-server/adapters/appnexus" "github.com/prebid/prebid-server/adapters/audienceNetwork" @@ -123,7 +124,6 @@ import ( "github.com/prebid/prebid-server/adapters/ucfunnel" "github.com/prebid/prebid-server/adapters/unicorn" "github.com/prebid/prebid-server/adapters/unruly" - "github.com/prebid/prebid-server/adapters/valueimpression" "github.com/prebid/prebid-server/adapters/videobyte" "github.com/prebid/prebid-server/adapters/visx" "github.com/prebid/prebid-server/adapters/vrtcal" @@ -168,6 +168,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderAJA: aja.Builder, openrtb_ext.BidderAlgorix: algorix.Builder, openrtb_ext.BidderAMX: amx.Builder, + openrtb_ext.BidderApacdex: apacdex.Builder, openrtb_ext.BidderApplogy: applogy.Builder, openrtb_ext.BidderAppnexus: appnexus.Builder, openrtb_ext.BidderAudienceNetwork: audienceNetwork.Builder, @@ -241,6 +242,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderPubmatic: pubmatic.Builder, openrtb_ext.BidderPubnative: pubnative.Builder, openrtb_ext.BidderPulsepoint: pulsepoint.Builder, + openrtb_ext.BidderQuantumdex: apacdex.Builder, openrtb_ext.BidderRevcontent: revcontent.Builder, openrtb_ext.BidderRhythmone: rhythmone.Builder, openrtb_ext.BidderRichaudience: richaudience.Builder, @@ -267,7 +269,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderUcfunnel: ucfunnel.Builder, openrtb_ext.BidderUnicorn: unicorn.Builder, openrtb_ext.BidderUnruly: unruly.Builder, - openrtb_ext.BidderValueImpression: valueimpression.Builder, + openrtb_ext.BidderValueImpression: apacdex.Builder, openrtb_ext.BidderVerizonMedia: yahoossp.Builder, openrtb_ext.BidderVideoByte: videobyte.Builder, openrtb_ext.BidderViewdeos: adtelligent.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index d02a7a48320..941f1a561f0 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -103,6 +103,7 @@ const ( BidderAJA BidderName = "aja" BidderAlgorix BidderName = "algorix" BidderAMX BidderName = "amx" + BidderApacdex BidderName = "apacdex" BidderApplogy BidderName = "applogy" BidderAppnexus BidderName = "appnexus" BidderAudienceNetwork BidderName = "audienceNetwork" @@ -176,6 +177,7 @@ const ( BidderPubmatic BidderName = "pubmatic" BidderPubnative BidderName = "pubnative" BidderPulsepoint BidderName = "pulsepoint" + BidderQuantumdex BidderName = "quantumdex" BidderRevcontent BidderName = "revcontent" BidderRhythmone BidderName = "rhythmone" BidderRichaudience BidderName = "richaudience" @@ -247,6 +249,7 @@ func CoreBidderNames() []BidderName { BidderAJA, BidderAlgorix, BidderAMX, + BidderApacdex, BidderApplogy, BidderAppnexus, BidderAudienceNetwork, @@ -320,6 +323,7 @@ func CoreBidderNames() []BidderName { BidderPubmatic, BidderPubnative, BidderPulsepoint, + BidderQuantumdex, BidderRevcontent, BidderRhythmone, BidderRichaudience, diff --git a/openrtb_ext/imp_apacdex.go b/openrtb_ext/imp_apacdex.go new file mode 100644 index 00000000000..dc8fb15b123 --- /dev/null +++ b/openrtb_ext/imp_apacdex.go @@ -0,0 +1,7 @@ +package openrtb_ext + +type ExtImpApacdex struct { + PlacementID string `json:"placementId"` + SiteID string `json:"siteId"` + FloorPrice float64 `json:"floorPrice"` +} diff --git a/openrtb_ext/imp_valueimpression.go b/openrtb_ext/imp_valueimpression.go deleted file mode 100644 index 7c5c70ee0a7..00000000000 --- a/openrtb_ext/imp_valueimpression.go +++ /dev/null @@ -1,5 +0,0 @@ -package openrtb_ext - -type ExtImpValueImpression struct { - SiteId string `json:"siteId"` -} diff --git a/static/bidder-info/apacdex.yaml b/static/bidder-info/apacdex.yaml new file mode 100644 index 00000000000..2e8cd08f621 --- /dev/null +++ b/static/bidder-info/apacdex.yaml @@ -0,0 +1,20 @@ +maintainer: + email: "support@apacdex.com" +modifyingVastXmlAllowed: false +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video +userSync: + default: iframe + iframe: + url: https://sync.quantumdex.io/usersync/pbs?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}} + userMacro: "[UID]" + redirect: + url: "https://sync.quantumdex.io/getuid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}" + userMacro: "[UID]" diff --git a/static/bidder-info/quantumdex.yaml b/static/bidder-info/quantumdex.yaml new file mode 100644 index 00000000000..2e8cd08f621 --- /dev/null +++ b/static/bidder-info/quantumdex.yaml @@ -0,0 +1,20 @@ +maintainer: + email: "support@apacdex.com" +modifyingVastXmlAllowed: false +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video +userSync: + default: iframe + iframe: + url: https://sync.quantumdex.io/usersync/pbs?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}} + userMacro: "[UID]" + redirect: + url: "https://sync.quantumdex.io/getuid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}" + userMacro: "[UID]" diff --git a/static/bidder-info/valueimpression.yaml b/static/bidder-info/valueimpression.yaml index 0782f897f2a..2e8cd08f621 100644 --- a/static/bidder-info/valueimpression.yaml +++ b/static/bidder-info/valueimpression.yaml @@ -1,5 +1,6 @@ maintainer: - email: "info@valueimpression.com" + email: "support@apacdex.com" +modifyingVastXmlAllowed: false capabilities: app: mediaTypes: @@ -10,6 +11,10 @@ capabilities: - banner - video userSync: + default: iframe + iframe: + url: https://sync.quantumdex.io/usersync/pbs?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}} + userMacro: "[UID]" redirect: - url: "https://rtb.valueimpression.com/usersync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" - userMacro: "$UID" + url: "https://sync.quantumdex.io/getuid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}" + userMacro: "[UID]" diff --git a/static/bidder-params/apacdex.json b/static/bidder-params/apacdex.json new file mode 100644 index 00000000000..0130fcee1c7 --- /dev/null +++ b/static/bidder-params/apacdex.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Apacdex Adapter Params", + "description": "A schema which validates params accepted by the Apacdex adapter", + "type": "object", + "properties": { + "placementId": { + "type": "string", + "description": "Placement ID provided by Apacdex" + }, + "siteId": { + "type": "string", + "description": "Publisher site ID from Apacdex" + }, + "floorPrice": { + "type": "number", + "description": "CPM bidfloor in USD" + } + }, + "oneOf": [ + { + "required": [ + "placementId" + ] + }, + { + "required": [ + "siteId" + ] + } + ] +} \ No newline at end of file diff --git a/static/bidder-params/quantumdex.json b/static/bidder-params/quantumdex.json new file mode 100644 index 00000000000..3ef9abe34c6 --- /dev/null +++ b/static/bidder-params/quantumdex.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Quantumdex Adapter Params", + "description": "A schema which validates params accepted by the Quantumdex adapter", + "type": "object", + "properties": { + "placementId": { + "type": "string", + "description": "Placement ID provided by Quantumdex" + }, + "siteId": { + "type": "string", + "description": "Publisher site ID from Quantumdex" + }, + "floorPrice": { + "type": "number", + "description": "CPM bidfloor in USD" + } + }, + "oneOf": [ + { + "required": [ + "placementId" + ] + }, + { + "required": [ + "siteId" + ] + } + ] +} \ No newline at end of file diff --git a/static/bidder-params/valueimpression.json b/static/bidder-params/valueimpression.json index 5b9c32c592e..793e940eb11 100644 --- a/static/bidder-params/valueimpression.json +++ b/static/bidder-params/valueimpression.json @@ -1,15 +1,32 @@ - { - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "ValueImpression Adapter Params", - "description": "Schema to validate params accepted by the ValueImpression adapter", - - "type": "object", - "properties": { - "siteId": { - "type": "string", - "description": "Site ID" - } + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Valueimpression Adapter Params", + "description": "A schema which validates params accepted by the Valueimpression adapter", + "type": "object", + "properties": { + "placementId": { + "type": "string", + "description": "Placement ID provided by Valueimpression" }, - "required": ["siteId"] - } + "siteId": { + "type": "string", + "description": "Publisher site ID from Valueimpression" + }, + "floorPrice": { + "type": "number", + "description": "CPM bidfloor in USD" + } + }, + "oneOf": [ + { + "required": [ + "placementId" + ] + }, + { + "required": [ + "siteId" + ] + } + ] +} \ No newline at end of file From 6c33ed6bc9cf3a7405015b684d768015a503e3c1 Mon Sep 17 00:00:00 2001 From: Mikael Lundin Date: Tue, 4 Jan 2022 19:16:11 +0100 Subject: [PATCH 04/14] Adnuntius: Read device information from ortb Request (#2112) --- adapters/adnuntius/adnuntius.go | 13 +- .../supplemental/send-header-information.json | 122 ++++++++++++++++++ 2 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json diff --git a/adapters/adnuntius/adnuntius.go b/adapters/adnuntius/adnuntius.go index f556081ae70..da66e4433ec 100644 --- a/adapters/adnuntius/adnuntius.go +++ b/adapters/adnuntius/adnuntius.go @@ -74,10 +74,19 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E return a.generateRequests(*request) } -func setHeaders() http.Header { +func setHeaders(ortbRequest openrtb2.BidRequest) http.Header { + headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") headers.Add("Accept", "application/json") + if ortbRequest.Device != nil { + if ortbRequest.Device.IP != "" { + headers.Add("X-Forwarded-For", ortbRequest.Device.IP) + } + if ortbRequest.Device.UA != "" { + headers.Add("user-agent", ortbRequest.Device.UA) + } + } return headers } @@ -113,7 +122,7 @@ func makeEndpointUrl(ortbRequest openrtb2.BidRequest, a *adapter) (string, []err func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters.RequestData, []error) { var requestData []*adapters.RequestData networkAdunitMap := make(map[string][]adnAdunit) - headers := setHeaders() + headers := setHeaders(ortbRequest) endpoint, err := makeEndpointUrl(ortbRequest, a) if err != nil { diff --git a/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json b/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json new file mode 100644 index 00000000000..96ddff858ac --- /dev/null +++ b/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json @@ -0,0 +1,122 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "user": { + "id": "1kjh3429kjh295jkl", + "ext": { + "consent": "CONSENT_STRING" + } + }, + "device": { + "ip": "158.174.81.143", + "ua": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Mobile Safari/537.36" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "auId": "123" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "X-Forwarded-For": [ + "158.174.81.143" + ], + "User-Agent": [ + "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Mobile Safari/537.36" + ] + }, + "uri": "http://whatever.url?format=json&tzo=0", + "body": { + "adUnits": [ + { + "auId": "123", + "targetId": "123-test-imp-id" + } + ], + "metaData": { + "usi": "1kjh3429kjh295jkl" + }, + "context": "unknown" + } + }, + "mockResponse": { + "status": 200, + "body": { + "adUnits": [ + { + "auId": "0000000000000123", + "targetId": "123-test-imp-id", + "html": "", + "responseId": "adn-rsp-900646517", + "ads": [ + { + "destinationUrls": { + "url": "http://www.google.com" + }, + "bid": { + "amount": 20.0, + "currency": "NOK" + }, + "adId": "adn-id-1559784094", + "creativeWidth": "980", + "creativeHeight": "240", + "creativeId": "jn9hpzvlsf8cpdmm", + "lineItemId": "q7y9qm5b0xt9htrv" + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "adn-id-1559784094", + "impid": "test-imp-id", + "price": 20000, + "adm": "", + "adid": "adn-id-1559784094", + "adomain": ["google.com"], + "cid": "q7y9qm5b0xt9htrv", + "crid": "jn9hpzvlsf8cpdmm", + "w": 980, + "h": 240 + }, + "type": "banner" + } + ], + "currency": "NOK" + } + ] +} From 9524fdb6a53aec02c05e184b07f449d477c0f686 Mon Sep 17 00:00:00 2001 From: "Takaaki.Kojima" Date: Fri, 7 Jan 2022 02:29:14 +0900 Subject: [PATCH 05/14] Adgeneration: Update request to include device and app related info in headers and query params (#2109) --- adapters/adgeneration/adgeneration.go | 32 +++- adapters/adgeneration/adgeneration_test.go | 2 +- .../exemplary/single-banner-android.json | 166 ++++++++++++++++++ .../exemplary/single-banner-ios.json | 166 ++++++++++++++++++ .../exemplary/single-banner.json | 11 +- .../supplemental/204-bid-response.json | 2 +- .../supplemental/400-bid-response.json | 2 +- .../supplemental/no-bid-response.json | 2 +- 8 files changed, 373 insertions(+), 10 deletions(-) create mode 100644 adapters/adgeneration/adgenerationtest/exemplary/single-banner-android.json create mode 100644 adapters/adgeneration/adgenerationtest/exemplary/single-banner-ios.json diff --git a/adapters/adgeneration/adgeneration.go b/adapters/adgeneration/adgeneration.go index 110ec5ce98a..55fafde1d85 100644 --- a/adapters/adgeneration/adgeneration.go +++ b/adapters/adgeneration/adgeneration.go @@ -55,8 +55,13 @@ func (adg *AdgenerationAdapter) MakeRequests(request *openrtb2.BidRequest, reqIn headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") headers.Add("Accept", "application/json") - if request.Device != nil && len(request.Device.UA) > 0 { - headers.Add("User-Agent", request.Device.UA) + if request.Device != nil { + if len(request.Device.UA) > 0 { + headers.Add("User-Agent", request.Device.UA) + } + if len(request.Device.IP) > 0 { + headers.Add("X-Forwarded-For", request.Device.IP) + } } bidRequestArray := make([]*adapters.RequestData, 0, numRequests) @@ -102,7 +107,6 @@ func (adg *AdgenerationAdapter) getRawQuery(id string, request *openrtb2.BidRequ v := url.Values{} v.Set("posall", "SSPLOC") v.Set("id", id) - v.Set("sdktype", "0") v.Set("hb", "true") v.Set("t", "json3") v.Set("currency", adg.getCurrency(request)) @@ -112,12 +116,32 @@ func (adg *AdgenerationAdapter) getRawQuery(id string, request *openrtb2.BidRequ if adSize != "" { v.Set("sizes", adSize) } + if request.Device != nil && request.Device.OS == "android" { + v.Set("sdktype", "1") + } else if request.Device != nil && request.Device.OS == "ios" { + v.Set("sdktype", "2") + } else { + v.Set("sdktype", "0") + } if request.Site != nil && request.Site.Page != "" { v.Set("tp", request.Site.Page) } if request.Source != nil && request.Source.TID != "" { v.Set("transactionid", request.Source.TID) } + if request.App != nil && request.App.Bundle != "" { + v.Set("appbundle", request.App.Bundle) + } + if request.App != nil && request.App.Name != "" { + v.Set("appname", request.App.Name) + } + if request.Device != nil && request.Device.OS == "ios" && request.Device.IFA != "" { + v.Set("idfa", request.Device.IFA) + } + if request.Device != nil && request.Device.OS == "android" && request.Device.IFA != "" { + v.Set("advertising_id", request.Device.IFA) + } + return &v } @@ -263,7 +287,7 @@ func removeWrapper(ad string) string { func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { bidder := &AdgenerationAdapter{ config.Endpoint, - "1.0.2", + "1.0.3", "JPY", } return bidder, nil diff --git a/adapters/adgeneration/adgeneration_test.go b/adapters/adgeneration/adgeneration_test.go index d5d93ac4e0b..c186f19f4c5 100644 --- a/adapters/adgeneration/adgeneration_test.go +++ b/adapters/adgeneration/adgeneration_test.go @@ -23,7 +23,7 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "adgenerationtest", bidder) } -func TestgetRequestUri(t *testing.T) { +func TestGetRequestUri(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.BidderAdgeneration, config.Adapter{ Endpoint: "https://d.socdm.com/adsv/v1"}) diff --git a/adapters/adgeneration/adgenerationtest/exemplary/single-banner-android.json b/adapters/adgeneration/adgenerationtest/exemplary/single-banner-android.json new file mode 100644 index 00000000000..487d44692e0 --- /dev/null +++ b/adapters/adgeneration/adgenerationtest/exemplary/single-banner-android.json @@ -0,0 +1,166 @@ +{ + "mockBidRequest":{ + "id": "some-request-id", + "site": { + "page": "http://example.com/test.html" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36", + "ip": "0.0.0.0", + "os": "android", + "ifa": "advertising_id" + }, + "app": { + "name": "adgneration" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "id": "58278" + } + } + } + ], + "tmax": 500 + }, + "httpCalls": [ + { + "internalRequest": { + "id": "some-request-id", + "site": { + "page": "http://example.com/test.html" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "id": "58278" + } + } + } + ], + "tmax": 500 + }, + "expectedRequest":{ + "uri": "https://d.socdm.com/adsv/v1?adapterver=1.0.3&advertising_id=advertising_id&appname=adgneration¤cy=JPY&hb=true&id=58278&posall=SSPLOC&sdkname=prebidserver&sdktype=1&sizes=300x250&t=json3&tp=http%3A%2F%2Fexample.com%2Ftest.html", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "User-Agent": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36" + ], + "X-Forwarded-For": [ + "0.0.0.0" + ] + } + }, + "mockResponse":{ + "status": 200, + "body": { + "ad": "\n \n \n