From 949d1f05e4ff5cd0f0f5c16d79e033865e0f2168 Mon Sep 17 00:00:00 2001 From: Brian Schaaf Date: Fri, 3 Mar 2023 21:47:21 +0000 Subject: [PATCH 1/8] gdpr test fails idk why --- adapters/pwbid/params_test.go | 42 ++++++++ adapters/pwbid/pwbid.go | 100 ++++++++++++++++++ adapters/pwbid/pwbid_test.go | 21 ++++ .../pwbid/pwbidtest/exemplary/banner.json | 87 +++++++++++++++ .../pwbid/pwbidtest/exemplary/native.json | 87 +++++++++++++++ .../response-200-without-body.json | 56 ++++++++++ .../pwbidtest/supplemental/response-204.json | 51 +++++++++ .../pwbidtest/supplemental/response-400.json | 56 ++++++++++ .../pwbidtest/supplemental/response-500.json | 56 ++++++++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_pwbid.go | 7 ++ static/bidder-info/pwbid.yaml | 18 ++++ static/bidder-params/pwbid.json | 21 ++++ 14 files changed, 606 insertions(+) create mode 100644 adapters/pwbid/params_test.go create mode 100644 adapters/pwbid/pwbid.go create mode 100644 adapters/pwbid/pwbid_test.go create mode 100644 adapters/pwbid/pwbidtest/exemplary/banner.json create mode 100644 adapters/pwbid/pwbidtest/exemplary/native.json create mode 100644 adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json create mode 100644 adapters/pwbid/pwbidtest/supplemental/response-204.json create mode 100644 adapters/pwbid/pwbidtest/supplemental/response-400.json create mode 100644 adapters/pwbid/pwbidtest/supplemental/response-500.json create mode 100644 openrtb_ext/imp_pwbid.go create mode 100644 static/bidder-info/pwbid.yaml create mode 100644 static/bidder-params/pwbid.json diff --git a/adapters/pwbid/params_test.go b/adapters/pwbid/params_test.go new file mode 100644 index 00000000000..ef8068f8d38 --- /dev/null +++ b/adapters/pwbid/params_test.go @@ -0,0 +1,42 @@ +package pwbid + +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.BidderPWBid, 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.BidderPWBid, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + } +} + +var validParams = []string{ + `{"siteId": "39f43a"}`, +} + +var invalidParams = []string{ + `{"siteId": 42}`, +} diff --git a/adapters/pwbid/pwbid.go b/adapters/pwbid/pwbid.go new file mode 100644 index 00000000000..6ff2de8e175 --- /dev/null +++ b/adapters/pwbid/pwbid.go @@ -0,0 +1,100 @@ +package pwbid + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/prebid/openrtb/v17/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 PwbidAdapter struct { + siteId string + bidFloor float32 + isTest bool +} + +type adapter struct { + endpoint string +} + +// Builder builds a new instance of the Foo adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + + return bidder, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + requestJSON, err := json.Marshal(request) + if err != nil { + return nil, []error{err} + } + + requestData := &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: requestJSON, + } + + return []*adapters.RequestData{requestData}, 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{err} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + + for _, seatBid := range response.SeatBid { + for i, bid := range seatBid.Bid { + bidType := getMediaTypeForBid(bid) + b := &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + } + bidResponse.Bids = append(bidResponse.Bids, b) + } + } + + return bidResponse, nil +} + +func getMediaTypeForBid(bid openrtb2.Bid) openrtb_ext.BidType { + if bid.Ext != nil { + var bidExt openrtb_ext.ExtBid + err := json.Unmarshal(bid.Ext, &bidExt) + if err == nil && bidExt.Prebid != nil { + bidType, _ := openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) + return bidType + } + } + + return "" +} diff --git a/adapters/pwbid/pwbid_test.go b/adapters/pwbid/pwbid_test.go new file mode 100644 index 00000000000..bc3234a87b6 --- /dev/null +++ b/adapters/pwbid/pwbid_test.go @@ -0,0 +1,21 @@ +package pwbid + +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.BidderPWBid, config.Adapter{ + Endpoint: "https://bid.pubwise.io/prebid"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 842, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "pwbid_test", bidder) +} diff --git a/adapters/pwbid/pwbidtest/exemplary/banner.json b/adapters/pwbid/pwbidtest/exemplary/banner.json new file mode 100644 index 00000000000..feb947d43fe --- /dev/null +++ b/adapters/pwbid/pwbidtest/exemplary/banner.json @@ -0,0 +1,87 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "3943fa" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "3943fa" + } + } + } + ], + "site": { + "publisher": { + "idk": "idk wtf this is" + } + }, + "regs": { "ext": { "gdpr": 0 } } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "pwbid", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728 + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/pwbid/pwbidtest/exemplary/native.json b/adapters/pwbid/pwbidtest/exemplary/native.json new file mode 100644 index 00000000000..feb947d43fe --- /dev/null +++ b/adapters/pwbid/pwbidtest/exemplary/native.json @@ -0,0 +1,87 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "3943fa" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "3943fa" + } + } + } + ], + "site": { + "publisher": { + "idk": "idk wtf this is" + } + }, + "regs": { "ext": { "gdpr": 0 } } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "pwbid", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728 + }] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json b/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json new file mode 100644 index 00000000000..ffa5f9eace5 --- /dev/null +++ b/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json @@ -0,0 +1,56 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ], + "site": { + "publisher": { + "id": "73" + } + } + } + }, + "mockResponse": { + "status": 200 + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "unexpected end of JSON input", + "comparison": "literal" + } + ] +} diff --git a/adapters/pwbid/pwbidtest/supplemental/response-204.json b/adapters/pwbid/pwbidtest/supplemental/response-204.json new file mode 100644 index 00000000000..3951fde1ab1 --- /dev/null +++ b/adapters/pwbid/pwbidtest/supplemental/response-204.json @@ -0,0 +1,51 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ], + "site": { + "publisher": { + "id": "73" + } + } + } + }, + "mockResponse": { + "status": 204 + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/pwbid/pwbidtest/supplemental/response-400.json b/adapters/pwbid/pwbidtest/supplemental/response-400.json new file mode 100644 index 00000000000..6d70bd745bd --- /dev/null +++ b/adapters/pwbid/pwbidtest/supplemental/response-400.json @@ -0,0 +1,56 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ], + "site": { + "publisher": { + "id": "73" + } + } + } + }, + "mockResponse": { + "status": 400 + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/pwbid/pwbidtest/supplemental/response-500.json b/adapters/pwbid/pwbidtest/supplemental/response-500.json new file mode 100644 index 00000000000..f2e0f544e26 --- /dev/null +++ b/adapters/pwbid/pwbidtest/supplemental/response-500.json @@ -0,0 +1,56 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ], + "site": { + "publisher": { + "id": "73" + } + } + } + }, + "mockResponse": { + "status": 500 + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index b784acf9567..d523f3d82da 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -121,6 +121,7 @@ import ( "github.com/prebid/prebid-server/adapters/pubmatic" "github.com/prebid/prebid-server/adapters/pubnative" "github.com/prebid/prebid-server/adapters/pulsepoint" + "github.com/prebid/prebid-server/adapters/pwbid" "github.com/prebid/prebid-server/adapters/revcontent" "github.com/prebid/prebid-server/adapters/rhythmone" "github.com/prebid/prebid-server/adapters/richaudience" @@ -297,6 +298,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.BidderPWBid: pwbid.Builder, openrtb_ext.BidderQuantumdex: apacdex.Builder, openrtb_ext.BidderRevcontent: revcontent.Builder, openrtb_ext.BidderRhythmone: rhythmone.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 9595c97677a..dc79ac56d15 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -212,6 +212,7 @@ const ( BidderPubmatic BidderName = "pubmatic" BidderPubnative BidderName = "pubnative" BidderPulsepoint BidderName = "pulsepoint" + BidderPWBid BidderName = "pwbid" BidderQuantumdex BidderName = "quantumdex" BidderRevcontent BidderName = "revcontent" BidderRhythmone BidderName = "rhythmone" @@ -392,6 +393,7 @@ func CoreBidderNames() []BidderName { BidderPubmatic, BidderPubnative, BidderPulsepoint, + BidderPWBid, BidderQuantumdex, BidderRevcontent, BidderRhythmone, diff --git a/openrtb_ext/imp_pwbid.go b/openrtb_ext/imp_pwbid.go new file mode 100644 index 00000000000..d15643c2fec --- /dev/null +++ b/openrtb_ext/imp_pwbid.go @@ -0,0 +1,7 @@ +package openrtb_ext + +type ExtImpPwbid struct { + siteId string `json:"siteId"` + bidFloor float32 `json:"bidFloor"` + isTest string `json:"isTest"` +} diff --git a/static/bidder-info/pwbid.yaml b/static/bidder-info/pwbid.yaml new file mode 100644 index 00000000000..f05fe34cf64 --- /dev/null +++ b/static/bidder-info/pwbid.yaml @@ -0,0 +1,18 @@ +endpoint: "https://bid.pubwise.io/prebid" +maintainer: + email: info@pubwise.io +gvlVendorID: 842 +capabilities: + app: + mediaTypes: + - banner + - native + site: + mediaTypes: + - banner + - native +# userSync: +# redirect: +# url: +# userMacro: $UID +# idk what to do here yet \ No newline at end of file diff --git a/static/bidder-params/pwbid.json b/static/bidder-params/pwbid.json new file mode 100644 index 00000000000..e973d156223 --- /dev/null +++ b/static/bidder-params/pwbid.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "PubWise (pwbid) Adapter Params", + "description": "A schema which validates params accepted by the PubWise (pwbid) adapter", + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "The site ID provided by the PubWise system" + }, + "bidFloor": { + "type": "number", + "description": "Value to pass as the bidfloor for this bid" + }, + "isTest": { + "type": "boolean", + "description": "A boolean to indicate 100% fill test placement request" + } + }, + "required": ["siteId"] +} From 3b606e07961fa8e7d538464224860945f9654091 Mon Sep 17 00:00:00 2001 From: Brian Schaaf Date: Thu, 9 Mar 2023 14:40:02 +0000 Subject: [PATCH 2/8] check in --- adapters/pwbid/pwbid.go | 15 +++-- adapters/pwbid/pwbid_test.go | 2 +- .../pwbid/pwbidtest/exemplary/banner.json | 56 ++++++++++--------- .../pwbid/pwbidtest/exemplary/native.json | 50 +++++++++-------- .../response-200-without-body.json | 7 +-- .../pwbidtest/supplemental/response-204.json | 7 +-- .../pwbidtest/supplemental/response-400.json | 7 +-- .../pwbidtest/supplemental/response-500.json | 7 +-- static/bidder-info/pwbid.yaml | 9 ++- 9 files changed, 76 insertions(+), 84 deletions(-) diff --git a/adapters/pwbid/pwbid.go b/adapters/pwbid/pwbid.go index 6ff2de8e175..ace21851bc2 100644 --- a/adapters/pwbid/pwbid.go +++ b/adapters/pwbid/pwbid.go @@ -22,7 +22,6 @@ type adapter struct { endpoint string } -// Builder builds a new instance of the Foo adapter for the given bidder with the given config. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { bidder := &adapter{ endpoint: config.Endpoint, @@ -74,7 +73,10 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R for _, seatBid := range response.SeatBid { for i, bid := range seatBid.Bid { - bidType := getMediaTypeForBid(bid) + bidType, typeerr := getMediaTypeForBid(bid) + if typeerr != nil { + return nil, []error{typeerr} + } b := &adapters.TypedBid{ Bid: &seatBid.Bid[i], BidType: bidType, @@ -86,15 +88,16 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R return bidResponse, nil } -func getMediaTypeForBid(bid openrtb2.Bid) openrtb_ext.BidType { +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 { - bidType, _ := openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) - return bidType + return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) } } - return "" + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to parse bid mediatype for impression \"%s\"", bid.ImpID), + } } diff --git a/adapters/pwbid/pwbid_test.go b/adapters/pwbid/pwbid_test.go index bc3234a87b6..21a4194249e 100644 --- a/adapters/pwbid/pwbid_test.go +++ b/adapters/pwbid/pwbid_test.go @@ -17,5 +17,5 @@ func TestJsonSamples(t *testing.T) { t.Fatalf("Builder returned unexpected error %v", buildErr) } - adapterstest.RunJSONBidderTest(t, "pwbid_test", bidder) + adapterstest.RunJSONBidderTest(t, "pwbidtest", bidder) } diff --git a/adapters/pwbid/pwbidtest/exemplary/banner.json b/adapters/pwbid/pwbidtest/exemplary/banner.json index feb947d43fe..ba618cb8cf1 100644 --- a/adapters/pwbid/pwbidtest/exemplary/banner.json +++ b/adapters/pwbid/pwbidtest/exemplary/banner.json @@ -1,11 +1,16 @@ { "mockBidRequest": { - "id": "test-request-id", + "id": "test-request-id-banner", "imp": [ { - "id": "test-imp-id", + "id": "test-imp-id-banner", "banner": { - "format": [{"w": 728, "h": 90}] + "format": [ + { + "w": 728, + "h": 90 + } + ] }, "ext": { "bidder": { @@ -20,12 +25,17 @@ "expectedRequest": { "uri": "https://bid.pubwise.io/prebid", "body": { - "id": "test-request-id", + "id": "test-request-id-banner", "imp": [ { - "id": "test-imp-id", + "id": "test-imp-id-banner", "banner": { - "format": [{"w": 728, "h": 90}] + "format": [ + { + "w": 728, + "h": 90 + } + ] }, "ext": { "bidder": { @@ -33,31 +43,27 @@ } } } - ], - "site": { - "publisher": { - "idk": "idk wtf this is" - } - }, - "regs": { "ext": { "gdpr": 0 } } + ] } }, "mockResponse": { "status": 200, "body": { - "id": "test-request-id", + "id": "test-request-id-banner", "seatbid": [ { "seat": "pwbid", - "bid": [{ - "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", - "price": 0.500000, - "adm": "some-test-ad", - "crid": "crid_10", - "h": 90, - "w": 728 - }] + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id-banner", + "price": 0.500000, + "adm": "some-test-ad-banner", + "crid": "crid_10", + "w": 728, + "h": 90 + } + ] } ], "cur": "USD" @@ -72,9 +78,9 @@ { "bid": { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", + "impid": "test-imp-id-banner", "price": 0.5, - "adm": "some-test-ad", + "adm": "some-test-ad-banner", "crid": "crid_10", "w": 728, "h": 90 diff --git a/adapters/pwbid/pwbidtest/exemplary/native.json b/adapters/pwbid/pwbidtest/exemplary/native.json index feb947d43fe..fcc2c157562 100644 --- a/adapters/pwbid/pwbidtest/exemplary/native.json +++ b/adapters/pwbid/pwbidtest/exemplary/native.json @@ -1,11 +1,16 @@ { "mockBidRequest": { - "id": "test-request-id", + "id": "test-request-id-native", "imp": [ { - "id": "test-imp-id", - "banner": { - "format": [{"w": 728, "h": 90}] + "id": "test-imp-id-native", + "native": { + "format": [ + { + "w": 728, + "h": 90 + } + ] }, "ext": { "bidder": { @@ -20,12 +25,17 @@ "expectedRequest": { "uri": "https://bid.pubwise.io/prebid", "body": { - "id": "test-request-id", + "id": "test-request-id-native", "imp": [ { - "id": "test-imp-id", - "banner": { - "format": [{"w": 728, "h": 90}] + "id": "test-imp-id-native", + "native": { + "format": [ + { + "w": 728, + "h": 90 + } + ] }, "ext": { "bidder": { @@ -33,30 +43,24 @@ } } } - ], - "site": { - "publisher": { - "idk": "idk wtf this is" - } - }, - "regs": { "ext": { "gdpr": 0 } } + ] } }, "mockResponse": { "status": 200, "body": { - "id": "test-request-id", + "id": "test-request-id-native", "seatbid": [ { "seat": "pwbid", "bid": [{ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", + "impid": "test-imp-id-native", "price": 0.500000, - "adm": "some-test-ad", + "adm": "some-test-ad-native", "crid": "crid_10", - "h": 90, - "w": 728 + "w": 728, + "h": 90 }] } ], @@ -72,14 +76,14 @@ { "bid": { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", + "impid": "test-imp-id-native", "price": 0.5, - "adm": "some-test-ad", + "adm": "some-test-ad-native", "crid": "crid_10", "w": 728, "h": 90 }, - "type": "banner" + "type": "native" } ] } diff --git a/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json b/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json index ffa5f9eace5..146ba93a27d 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json @@ -34,12 +34,7 @@ } } } - ], - "site": { - "publisher": { - "id": "73" - } - } + ] } }, "mockResponse": { diff --git a/adapters/pwbid/pwbidtest/supplemental/response-204.json b/adapters/pwbid/pwbidtest/supplemental/response-204.json index 3951fde1ab1..5fff7ee32cc 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-204.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-204.json @@ -34,12 +34,7 @@ } } } - ], - "site": { - "publisher": { - "id": "73" - } - } + ] } }, "mockResponse": { diff --git a/adapters/pwbid/pwbidtest/supplemental/response-400.json b/adapters/pwbid/pwbidtest/supplemental/response-400.json index 6d70bd745bd..d594e571243 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-400.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-400.json @@ -34,12 +34,7 @@ } } } - ], - "site": { - "publisher": { - "id": "73" - } - } + ] } }, "mockResponse": { diff --git a/adapters/pwbid/pwbidtest/supplemental/response-500.json b/adapters/pwbid/pwbidtest/supplemental/response-500.json index f2e0f544e26..fa3d4d063a8 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-500.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-500.json @@ -34,12 +34,7 @@ } } } - ], - "site": { - "publisher": { - "id": "73" - } - } + ] } }, "mockResponse": { diff --git a/static/bidder-info/pwbid.yaml b/static/bidder-info/pwbid.yaml index f05fe34cf64..22c113d4aa6 100644 --- a/static/bidder-info/pwbid.yaml +++ b/static/bidder-info/pwbid.yaml @@ -11,8 +11,7 @@ capabilities: mediaTypes: - banner - native -# userSync: -# redirect: -# url: -# userMacro: $UID -# idk what to do here yet \ No newline at end of file +userSync: + redirect: + url: https://gdpr-wrapper.privacymanager.io/gdpr/6543ee0a-dbc0-4ab5-bf52-3e12b1b58de8/gdpr-liveramp.js + userMacro: $UID \ No newline at end of file From 589c2913401b06439c005d3c2bc0349fdb29f087 Mon Sep 17 00:00:00 2001 From: Rothalack Date: Fri, 10 Mar 2023 22:08:32 +0000 Subject: [PATCH 3/8] everything working except gdpr --- adapters/pwbid/pwbid.go | 25 ++++++++----------- .../pwbid/pwbidtest/exemplary/native.json | 18 +++---------- .../pwbidtest/supplemental/response-400.json | 2 +- .../pwbidtest/supplemental/response-500.json | 2 +- 4 files changed, 17 insertions(+), 30 deletions(-) diff --git a/adapters/pwbid/pwbid.go b/adapters/pwbid/pwbid.go index ace21851bc2..d5e455254a4 100644 --- a/adapters/pwbid/pwbid.go +++ b/adapters/pwbid/pwbid.go @@ -12,12 +12,6 @@ import ( "github.com/prebid/prebid-server/openrtb_ext" ) -type PwbidAdapter struct { - siteId string - bidFloor float32 - isTest bool -} - type adapter struct { endpoint string } @@ -73,7 +67,7 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R for _, seatBid := range response.SeatBid { for i, bid := range seatBid.Bid { - bidType, typeerr := getMediaTypeForBid(bid) + bidType, typeerr := getMediaTypeForBid(request.Imp, bid) if typeerr != nil { return nil, []error{typeerr} } @@ -88,16 +82,19 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R return bidResponse, nil } -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)) +func getMediaTypeForBid(impressions []openrtb2.Imp, bid openrtb2.Bid) (openrtb_ext.BidType, error) { + for _, impression := range impressions { + if impression.ID == bid.ImpID { + if impression.Banner != nil { + return openrtb_ext.BidTypeBanner, nil + } + if impression.Native != nil { + return openrtb_ext.BidTypeNative, nil + } } } return "", &errortypes.BadServerResponse{ - Message: fmt.Sprintf("Failed to parse bid mediatype for impression \"%s\"", bid.ImpID), + Message: fmt.Sprintf("The impression with ID %s is not present into the request", bid.ImpID), } } diff --git a/adapters/pwbid/pwbidtest/exemplary/native.json b/adapters/pwbid/pwbidtest/exemplary/native.json index fcc2c157562..907c16d467a 100644 --- a/adapters/pwbid/pwbidtest/exemplary/native.json +++ b/adapters/pwbid/pwbidtest/exemplary/native.json @@ -5,16 +5,11 @@ { "id": "test-imp-id-native", "native": { - "format": [ - { - "w": 728, - "h": 90 - } - ] + "request": "" }, "ext": { "bidder": { - "siteId": "3943fa" + "siteId": "39f43a" } } } @@ -30,16 +25,11 @@ { "id": "test-imp-id-native", "native": { - "format": [ - { - "w": 728, - "h": 90 - } - ] + "request": "" }, "ext": { "bidder": { - "siteId": "3943fa" + "siteId": "39f43a" } } } diff --git a/adapters/pwbid/pwbidtest/supplemental/response-400.json b/adapters/pwbid/pwbidtest/supplemental/response-400.json index d594e571243..5d6d4d73baf 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-400.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-400.json @@ -44,7 +44,7 @@ ], "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "value": "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", "comparison": "literal" } ] diff --git a/adapters/pwbid/pwbidtest/supplemental/response-500.json b/adapters/pwbid/pwbidtest/supplemental/response-500.json index fa3d4d063a8..18741b25a54 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-500.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-500.json @@ -44,7 +44,7 @@ ], "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info.", "comparison": "literal" } ] From df7beb0bd12bf38e0ec95c3bdd197408b95864ba Mon Sep 17 00:00:00 2001 From: Rothalack Date: Wed, 15 Mar 2023 16:08:18 +0000 Subject: [PATCH 4/8] usersync update and video --- adapters/pwbid/pwbid.go | 3 +++ openrtb_ext/imp_pwbid.go | 6 +++--- static/bidder-info/pwbid.yaml | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/adapters/pwbid/pwbid.go b/adapters/pwbid/pwbid.go index d5e455254a4..92d8822b149 100644 --- a/adapters/pwbid/pwbid.go +++ b/adapters/pwbid/pwbid.go @@ -91,6 +91,9 @@ func getMediaTypeForBid(impressions []openrtb2.Imp, bid openrtb2.Bid) (openrtb_e if impression.Native != nil { return openrtb_ext.BidTypeNative, nil } + if impression.Video != nil { + return openrtb_ext.BidTypeVideo, nil + } } } diff --git a/openrtb_ext/imp_pwbid.go b/openrtb_ext/imp_pwbid.go index d15643c2fec..eb405f847a0 100644 --- a/openrtb_ext/imp_pwbid.go +++ b/openrtb_ext/imp_pwbid.go @@ -1,7 +1,7 @@ package openrtb_ext type ExtImpPwbid struct { - siteId string `json:"siteId"` - bidFloor float32 `json:"bidFloor"` - isTest string `json:"isTest"` + SiteId string `json:"siteId"` + BidFloor float32 `json:"bidFloor"` + IsTest string `json:"isTest"` } diff --git a/static/bidder-info/pwbid.yaml b/static/bidder-info/pwbid.yaml index 22c113d4aa6..ac6872738b4 100644 --- a/static/bidder-info/pwbid.yaml +++ b/static/bidder-info/pwbid.yaml @@ -7,11 +7,14 @@ capabilities: mediaTypes: - banner - native + - video site: mediaTypes: - banner - native + - video userSync: - redirect: - url: https://gdpr-wrapper.privacymanager.io/gdpr/6543ee0a-dbc0-4ab5-bf52-3e12b1b58de8/gdpr-liveramp.js - userMacro: $UID \ No newline at end of file + # PubWise supports user syncing, but requires configuration by the host. contact this + # bidder directly at the email address in this file to ask about enabling user sync. + supports: + - redirect \ No newline at end of file From 8dde2fec79b0549ec8e6e62e8184bcafe7bfb5d2 Mon Sep 17 00:00:00 2001 From: Brian Schaaf Date: Fri, 17 Mar 2023 13:56:37 +0000 Subject: [PATCH 5/8] video test --- adapters/pwbid/pwbidtest/exemplary/video.json | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 adapters/pwbid/pwbidtest/exemplary/video.json diff --git a/adapters/pwbid/pwbidtest/exemplary/video.json b/adapters/pwbid/pwbidtest/exemplary/video.json new file mode 100644 index 00000000000..b74c780d0a9 --- /dev/null +++ b/adapters/pwbid/pwbidtest/exemplary/video.json @@ -0,0 +1,91 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-video-id", + "video": { + "mimes": ["video/mp4"], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-video-id", + "video": { + "mimes": ["video/mp4"], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "siteId": "39f43a" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id-test-video-id", + "seatbid": [ + { + "seat": "test-seat", + "bid": [ + { + "id": "5dce6055-a93c-1fd0-8c29-14afc3e510fd", + "impid": "test-video-id", + "price": 0.1529, + "nurl": "test-win", + "adm": "test-video", + "adid": "92-288", + "adomain": ["advertiserdomain.com"], + "crid": "288", + "w": 300, + "h": 250 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "5dce6055-a93c-1fd0-8c29-14afc3e510fd", + "impid": "test-video-id", + "price": 0.1529, + "nurl": "test-win", + "adm": "test-video", + "adid": "92-288", + "adomain": ["advertiserdomain.com"], + "crid": "288", + "w": 300, + "h": 250 + }, + "type": "video" + } + ] + } + ] +} From 65105b09436a74c3b00577369dfb087dd135c232 Mon Sep 17 00:00:00 2001 From: Brian Schaaf Date: Wed, 29 Mar 2023 16:36:10 +0000 Subject: [PATCH 6/8] fixes --- adapters/pwbid/pwbid.go | 22 ++--- .../pwbidtest/exemplary/optional-params.json | 97 +++++++++++++++++++ .../pwbidtest/supplemental/response-400.json | 2 +- .../pwbidtest/supplemental/response-500.json | 2 +- openrtb_ext/imp_pwbid.go | 2 +- 5 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 adapters/pwbid/pwbidtest/exemplary/optional-params.json diff --git a/adapters/pwbid/pwbid.go b/adapters/pwbid/pwbid.go index 92d8822b149..5bbd8043a60 100644 --- a/adapters/pwbid/pwbid.go +++ b/adapters/pwbid/pwbid.go @@ -3,13 +3,13 @@ package pwbid import ( "encoding/json" "fmt" - "net/http" "github.com/prebid/openrtb/v17/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" + "github.com/prebid/prebid-server/util/httputil" ) type adapter struct { @@ -40,21 +40,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { - if responseData.StatusCode == http.StatusNoContent { + if httputil.IsResponseStatusCodeNoContent(responseData) { 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), - } + if err := httputil.CheckResponseStatusCodeForErrors(responseData); err != nil { return nil, []error{err} } @@ -67,9 +57,9 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R for _, seatBid := range response.SeatBid { for i, bid := range seatBid.Bid { - bidType, typeerr := getMediaTypeForBid(request.Imp, bid) - if typeerr != nil { - return nil, []error{typeerr} + bidType, typeErr := getMediaTypeForBid(request.Imp, bid) + if typeErr != nil { + return nil, []error{typeErr} } b := &adapters.TypedBid{ Bid: &seatBid.Bid[i], diff --git a/adapters/pwbid/pwbidtest/exemplary/optional-params.json b/adapters/pwbid/pwbidtest/exemplary/optional-params.json new file mode 100644 index 00000000000..a080be90208 --- /dev/null +++ b/adapters/pwbid/pwbidtest/exemplary/optional-params.json @@ -0,0 +1,97 @@ +{ + "mockBidRequest": { + "id": "test-request-id-banner", + "imp": [ + { + "id": "test-imp-id-banner", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "siteId": "3943fa", + "bidFloor": 0.10, + "isTest": false + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://bid.pubwise.io/prebid", + "body": { + "id": "test-request-id-banner", + "imp": [ + { + "id": "test-imp-id-banner", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "siteId": "3943fa", + "bidFloor": 0.10, + "isTest": false + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id-banner", + "seatbid": [ + { + "seat": "pwbid", + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id-banner", + "price": 0.500000, + "adm": "some-test-ad-banner", + "crid": "crid_10", + "w": 728, + "h": 90 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id-banner", + "price": 0.5, + "adm": "some-test-ad-banner", + "crid": "crid_10", + "w": 728, + "h": 90 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/pwbid/pwbidtest/supplemental/response-400.json b/adapters/pwbid/pwbidtest/supplemental/response-400.json index 5d6d4d73baf..d594e571243 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-400.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-400.json @@ -44,7 +44,7 @@ ], "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", "comparison": "literal" } ] diff --git a/adapters/pwbid/pwbidtest/supplemental/response-500.json b/adapters/pwbid/pwbidtest/supplemental/response-500.json index 18741b25a54..fa3d4d063a8 100644 --- a/adapters/pwbid/pwbidtest/supplemental/response-500.json +++ b/adapters/pwbid/pwbidtest/supplemental/response-500.json @@ -44,7 +44,7 @@ ], "expectedMakeBidsErrors": [ { - "value": "Unexpected status code: 500. Run with request.debug = 1 for more info.", + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", "comparison": "literal" } ] diff --git a/openrtb_ext/imp_pwbid.go b/openrtb_ext/imp_pwbid.go index eb405f847a0..d3f0da05dd6 100644 --- a/openrtb_ext/imp_pwbid.go +++ b/openrtb_ext/imp_pwbid.go @@ -3,5 +3,5 @@ package openrtb_ext type ExtImpPwbid struct { SiteId string `json:"siteId"` BidFloor float32 `json:"bidFloor"` - IsTest string `json:"isTest"` + IsTest bool `json:"isTest"` } From d12a0515545b2ff400ced1d80ed881186647b6df Mon Sep 17 00:00:00 2001 From: Brian Schaaf Date: Wed, 29 Mar 2023 17:01:05 +0000 Subject: [PATCH 7/8] append errors to not break loop --- adapters/pwbid/pwbid.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/adapters/pwbid/pwbid.go b/adapters/pwbid/pwbid.go index 5bbd8043a60..bcb8c137b98 100644 --- a/adapters/pwbid/pwbid.go +++ b/adapters/pwbid/pwbid.go @@ -40,6 +40,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte } func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + var errors []error + if httputil.IsResponseStatusCodeNoContent(responseData) { return nil, nil } @@ -59,8 +61,10 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R for i, bid := range seatBid.Bid { bidType, typeErr := getMediaTypeForBid(request.Imp, bid) if typeErr != nil { - return nil, []error{typeErr} + errors = append(errors, typeErr) + continue } + b := &adapters.TypedBid{ Bid: &seatBid.Bid[i], BidType: bidType, @@ -69,7 +73,7 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } } - return bidResponse, nil + return bidResponse, errors } func getMediaTypeForBid(impressions []openrtb2.Imp, bid openrtb2.Bid) (openrtb_ext.BidType, error) { From 9ff0a4c3de4ef299bd6d991fb1ccc9afd5f73f13 Mon Sep 17 00:00:00 2001 From: Brian Schaaf Date: Fri, 31 Mar 2023 15:37:42 +0000 Subject: [PATCH 8/8] better testing params --- adapters/pwbid/params_test.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/adapters/pwbid/params_test.go b/adapters/pwbid/params_test.go index ef8068f8d38..e16fd13c4dc 100644 --- a/adapters/pwbid/params_test.go +++ b/adapters/pwbid/params_test.go @@ -34,9 +34,16 @@ func TestInvalidParams(t *testing.T) { } var validParams = []string{ - `{"siteId": "39f43a"}`, + `{"siteId":"39f43a","bidFloor":0.10,"isTest":false}`, + `{"siteId":"39f43a","bidFloor":0.10,"isTest":true}`, + `{"siteId":"39f43a","bidFloor":0.10}`, + `{"siteId":"39f43a"}`, } var invalidParams = []string{ - `{"siteId": 42}`, + `{"siteId":42,"bidFloor":"asdf","isTest":123}`, + `{"siteId":}`, + `{"bidFloor":}`, + `{"bidFloor":0.10}`, + `null`, }