From 8689e0df95b9449a22d28eb5c56bbe9fc53f719c Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 7 Oct 2024 10:39:59 -0400 Subject: [PATCH 01/22] Sonobi: native and currency conversion support (#3889) Co-authored-by: bansawbanchee --- adapters/sonobi/sonobi.go | 39 +++- .../sonobi/sonobitest/exemplary/banner.json | 2 + .../sonobi/sonobitest/exemplary/native.json | 143 +++++++++++++++ .../sonobi/sonobitest/exemplary/no-bid.json | 2 + .../supplemental/currency-conversion.json | 172 ++++++++++++++++++ static/bidder-info/sonobi.yaml | 5 + 6 files changed, 355 insertions(+), 8 deletions(-) create mode 100644 adapters/sonobi/sonobitest/exemplary/native.json create mode 100644 adapters/sonobi/sonobitest/supplemental/currency-conversion.json diff --git a/adapters/sonobi/sonobi.go b/adapters/sonobi/sonobi.go index 65ea0d33e7c..afc1e5793d9 100644 --- a/adapters/sonobi/sonobi.go +++ b/adapters/sonobi/sonobi.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v2/adapters" @@ -53,6 +54,25 @@ func (a *SonobiAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adap reqCopy.Imp[0].TagID = sonobiExt.TagID + // If the bid floor currency is not USD, do the conversion to USD + if reqCopy.Imp[0].BidFloor > 0 && reqCopy.Imp[0].BidFloorCur != "" && strings.ToUpper(reqCopy.Imp[0].BidFloorCur) != "USD" { + + // Convert to US dollars + convertedValue, err := reqInfo.ConvertCurrency(reqCopy.Imp[0].BidFloor, reqCopy.Imp[0].BidFloorCur, "USD") + if err != nil { + errs = append(errs, err) + continue + } + + // Update after conversion. All imp elements inside request.Imp are shallow copies + // therefore, their non-pointer values are not shared memory and are safe to modify. + reqCopy.Imp[0].BidFloorCur = "USD" + reqCopy.Imp[0].BidFloor = convertedValue + } + + // Sonobi only bids in USD + reqCopy.Cur = append(make([]string, 0, 1), "USD") + adapterReq, errors := a.makeRequest(&reqCopy) if adapterReq != nil { adapterRequests = append(adapterRequests, adapterReq) @@ -115,19 +135,19 @@ func (a *SonobiAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalR } bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) + bidResponse.Currency = "USD" // Sonobi only bids in USD for _, sb := range bidResp.SeatBid { for i := range sb.Bid { - bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp) + bid := sb.Bid[i] + bidType, err := getMediaTypeForImp(bid.ImpID, internalRequest.Imp) if err != nil { - errs = append(errs, err) - } else { - b := &adapters.TypedBid{ - Bid: &sb.Bid[i], - BidType: bidType, - } - bidResponse.Bids = append(bidResponse.Bids, b) + return nil, []error{err} } + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + }) } } return bidResponse, errs @@ -140,6 +160,9 @@ func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, if imp.Banner == nil && imp.Video != nil { mediaType = openrtb_ext.BidTypeVideo } + if imp.Banner == nil && imp.Video == nil && imp.Native != nil { + mediaType = openrtb_ext.BidTypeNative + } return mediaType, nil } } diff --git a/adapters/sonobi/sonobitest/exemplary/banner.json b/adapters/sonobi/sonobitest/exemplary/banner.json index d60ddb44a8b..f3a39f74a27 100644 --- a/adapters/sonobi/sonobitest/exemplary/banner.json +++ b/adapters/sonobi/sonobitest/exemplary/banner.json @@ -1,5 +1,6 @@ { "mockBidRequest": { + "cur": ["GBP"], "id": "some-request-id", "site": { "page": "http://tester.go.sonobi.com", @@ -48,6 +49,7 @@ }, "uri": "https://apex.go.sonobi.com/prebid?partnerid=71d9d3d8af", "body": { + "cur": ["USD"], "id": "some-request-id", "imp": [ { diff --git a/adapters/sonobi/sonobitest/exemplary/native.json b/adapters/sonobi/sonobitest/exemplary/native.json new file mode 100644 index 00000000000..ff9eb4c4693 --- /dev/null +++ b/adapters/sonobi/sonobitest/exemplary/native.json @@ -0,0 +1,143 @@ +{ + "mockBidRequest": { + "cur": ["USD"], + "id": "some-request-id", + "site": { + "page": "http://tester.go.sonobi.com", + "domain": "sonobi.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "imp": [ + { + "id": "some-impression-id", + "native": { + "request": "{\"ver\":\"1.2\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":2,\"plcmtcnt\":3,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":1000}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":600,\"hmin\":600}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":3000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":60}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}},{\"id\":10,\"required\":0,\"data\":{\"type\":12,\"len\":15}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]},{\"event\":2,\"methods\":[1]}],\"privacy\":1}", + "ver": "1.2", + "battr": [ + 1, + 2, + 6, + 7, + 8, + 9, + 10, + 14 + ] + }, + "ext": { + "bidder": { + "TagID": "/7780971/apex_3pdm_integration" + } + } + } + ], + "test": 1, + "tmax": 500 + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ] + }, + "uri": "https://apex.go.sonobi.com/prebid?partnerid=71d9d3d8af", + "body": { + "cur": ["USD"], + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id", + "native": { + "request": "{\"ver\":\"1.2\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":2,\"plcmtcnt\":3,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":1000}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":600,\"hmin\":600}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":3000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":60}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}},{\"id\":10,\"required\":0,\"data\":{\"type\":12,\"len\":15}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]},{\"event\":2,\"methods\":[1]}],\"privacy\":1}", + "ver": "1.2", + "battr": [ + 1, + 2, + 6, + 7, + 8, + 9, + 10, + 14 + ] + }, + "tagid": "/7780971/apex_3pdm_integration", + "ext": { + "bidder": { + "TagID": "/7780971/apex_3pdm_integration" + } + } + } + ], + "site": { + "domain": "sonobi.com", + "page": "http://tester.go.sonobi.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "test": 1, + "tmax": 500 + }, + "impIDs": [ + "some-impression-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "1", + "impid": "some-impression-id", + "price": 2.8649999999999998, + "adm": "test-markup", + "adomain": [ + "sonobi.com" + ], + "cid": "house", + "crid": "sandbox" + + } + ], + "seat": "sonobi" + } + ], + "bidid": "sandbox_642305097", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "1", + "impid": "some-impression-id", + "price": 2.8649999999999998, + "adm": "test-markup", + "adomain": [ + "sonobi.com" + ], + "cid": "house", + "crid": "sandbox" + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/sonobi/sonobitest/exemplary/no-bid.json b/adapters/sonobi/sonobitest/exemplary/no-bid.json index ef31c9f2ba4..a43d1f670a0 100644 --- a/adapters/sonobi/sonobitest/exemplary/no-bid.json +++ b/adapters/sonobi/sonobitest/exemplary/no-bid.json @@ -1,5 +1,6 @@ { "mockBidRequest": { + "cur": ["USD"], "id": "some-request-id", "site": { "page": "http://tester.go.sonobi.com", @@ -48,6 +49,7 @@ }, "uri": "https://apex.go.sonobi.com/prebid?partnerid=71d9d3d8af", "body": { + "cur": ["USD"], "id": "some-request-id", "imp": [ { diff --git a/adapters/sonobi/sonobitest/supplemental/currency-conversion.json b/adapters/sonobi/sonobitest/supplemental/currency-conversion.json new file mode 100644 index 00000000000..522e1bd7326 --- /dev/null +++ b/adapters/sonobi/sonobitest/supplemental/currency-conversion.json @@ -0,0 +1,172 @@ +{ + "mockBidRequest": { + "cur": ["GBP"], + "id": "some-request-id", + "site": { + "page": "http://tester.go.sonobi.com", + "domain": "sonobi.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "w": 300, + "h": 250, + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "bidfloor": 1.00, + "bidfloorcur": "GBP", + "ext": { + "bidder": { + "TagID": "/7780971/apex_3pdm_integration" + } + } + } + ], + "ext": { + "prebid": { + "currency": { + "rates": { + "GBP": { + "USD": 0.05 + } + }, + "usepbsrates": false + } + } + }, + "test": 1, + "tmax": 500 + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ] + }, + "uri": "https://apex.go.sonobi.com/prebid?partnerid=71d9d3d8af", + "body": { + "cur": ["USD"], + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ], + "w": 300, + "h": 250 + }, + "bidfloor": 0.05, + "bidfloorcur": "USD", + "tagid": "/7780971/apex_3pdm_integration", + "ext": { + "bidder": { + "TagID": "/7780971/apex_3pdm_integration" + } + } + } + ], + "ext": { + "prebid": { + "currency": { + "rates": { + "GBP": { + "USD": 0.05 + } + }, + "usepbsrates": false + } + } + }, + "site": { + "domain": "sonobi.com", + "page": "http://tester.go.sonobi.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "test": 1, + "tmax": 500 + }, + "impIDs":["some-impression-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "1", + "impid": "some-impression-id", + "price": 2.8649999999999998, + "adm": "", + "adomain": [ + "sonobi.com" + ], + "cid": "house", + "crid": "sandbox", + "h": 1, + "w": 1 + } + ], + "seat": "sonobi" + } + ], + "bidid": "sandbox_642305097", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "1", + "impid": "some-impression-id", + "price": 2.8649999999999998, + "adm": "", + "adomain": [ + "sonobi.com" + ], + "cid": "house", + "crid": "sandbox", + "h": 1, + "w": 1 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/static/bidder-info/sonobi.yaml b/static/bidder-info/sonobi.yaml index 135bdacfe93..422ba610a6f 100644 --- a/static/bidder-info/sonobi.yaml +++ b/static/bidder-info/sonobi.yaml @@ -7,11 +7,16 @@ capabilities: mediaTypes: - banner - video + - native app: mediaTypes: - banner - video + - native userSync: + iframe: + url: "https://sync.go.sonobi.com/uc.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&loc={{.RedirectURL}}" + userMacro: "[UID]" redirect: url: "https://sync.go.sonobi.com/us.gif?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&loc={{.RedirectURL}}" userMacro: "[UID]" From d54c3ed22d437a590092870e611903208f840969 Mon Sep 17 00:00:00 2001 From: ysfbsf Date: Tue, 8 Oct 2024 15:42:40 +0200 Subject: [PATCH 02/22] New Adapter: Missena (#3761) --- adapters/missena/missena.go | 215 ++++++++++++++++++ adapters/missena/missena_test.go | 21 ++ .../missenatest/exemplary/multiple-imps.json | 129 +++++++++++ .../exemplary/simple-banner-ipv6.json | 105 +++++++++ .../missenatest/exemplary/simple-banner.json | 105 +++++++++ .../exemplary/valid-imp-error-imp.json | 129 +++++++++++ .../supplemental/error-ext-bidder.json | 25 ++ .../supplemental/error-imp-ext.json | 23 ++ .../missenatest/supplemental/status-204.json | 83 +++++++ .../missenatest/supplemental/status-400.json | 89 ++++++++ .../supplemental/status-not-200.json | 89 ++++++++ adapters/missena/params_test.go | 50 ++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_missena.go | 7 + static/bidder-info/missena.yaml | 16 ++ static/bidder-params/missena.json | 24 ++ 17 files changed, 1114 insertions(+) create mode 100644 adapters/missena/missena.go create mode 100644 adapters/missena/missena_test.go create mode 100644 adapters/missena/missenatest/exemplary/multiple-imps.json create mode 100644 adapters/missena/missenatest/exemplary/simple-banner-ipv6.json create mode 100644 adapters/missena/missenatest/exemplary/simple-banner.json create mode 100644 adapters/missena/missenatest/exemplary/valid-imp-error-imp.json create mode 100644 adapters/missena/missenatest/supplemental/error-ext-bidder.json create mode 100644 adapters/missena/missenatest/supplemental/error-imp-ext.json create mode 100644 adapters/missena/missenatest/supplemental/status-204.json create mode 100644 adapters/missena/missenatest/supplemental/status-400.json create mode 100644 adapters/missena/missenatest/supplemental/status-not-200.json create mode 100644 adapters/missena/params_test.go create mode 100644 openrtb_ext/imp_missena.go create mode 100644 static/bidder-info/missena.yaml create mode 100644 static/bidder-params/missena.json diff --git a/adapters/missena/missena.go b/adapters/missena/missena.go new file mode 100644 index 00000000000..93d4c2ba1cb --- /dev/null +++ b/adapters/missena/missena.go @@ -0,0 +1,215 @@ +package missena + +import ( + "encoding/json" + "fmt" + "net/http" + "text/template" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v2/config" + "github.com/prebid/prebid-server/v2/errortypes" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +type adapter struct { + endpoint string +} + +type MissenaAdRequest struct { + RequestId string `json:"request_id"` + Timeout int `json:"timeout"` + Referer string `json:"referer"` + RefererCanonical string `json:"referer_canonical"` + GDPRConsent string `json:"consent_string"` + GDPR bool `json:"consent_required"` + Placement string `json:"placement"` + TestMode string `json:"test"` +} + +type MissenaBidServerResponse struct { + Ad string `json:"ad"` + Cpm float64 `json:"cpm"` + Currency string `json:"currency"` + RequestId string `json:"requestId"` +} + +type MissenaInternalParams struct { + ApiKey string + RequestId string + Timeout int + Referer string + RefererCanonical string + GDPRConsent string + GDPR bool + Placement string + TestMode string +} + +type MissenaAdapter struct { + EndpointTemplate *template.Template +} + +// 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) makeRequest(missenaParams MissenaInternalParams, reqInfo *adapters.ExtraRequestInfo, impID string, request *openrtb2.BidRequest) (*adapters.RequestData, error) { + url := a.endpoint + "?t=" + missenaParams.ApiKey + + missenaRequest := MissenaAdRequest{ + RequestId: request.ID, + Timeout: 2000, + Referer: request.Site.Page, + RefererCanonical: request.Site.Domain, + GDPRConsent: missenaParams.GDPRConsent, + GDPR: missenaParams.GDPR, + Placement: missenaParams.Placement, + TestMode: missenaParams.TestMode, + } + + body, errm := json.Marshal(missenaRequest) + if errm != nil { + return nil, errm + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + + if request.Device != nil { + headers.Add("User-Agent", request.Device.UA) + if request.Device.IP != "" { + headers.Add("X-Forwarded-For", request.Device.IP) + } else if request.Device.IPv6 != "" { + headers.Add("X-Forwarded-For", request.Device.IPv6) + } + } + if request.Site != nil { + headers.Add("Referer", request.Site.Page) + } + + return &adapters.RequestData{ + Method: "POST", + Uri: url, + Headers: headers, + Body: body, + ImpIDs: []string{impID}, + }, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + + var httpRequests []*adapters.RequestData + var errors []error + gdprApplies, consentString := readGDPR(request) + + missenaInternalParams := MissenaInternalParams{ + GDPR: gdprApplies, + GDPRConsent: consentString, + } + + for _, imp := range request.Imp { + var bidderExt adapters.ExtImpBidder + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + errors = append(errors, &errortypes.BadInput{ + Message: "Error parsing bidderExt object", + }) + continue + } + + var missenaExt openrtb_ext.ExtImpMissena + if err := json.Unmarshal(bidderExt.Bidder, &missenaExt); err != nil { + errors = append(errors, &errortypes.BadInput{ + Message: "Error parsing missenaExt parameters", + }) + continue + } + + missenaInternalParams.ApiKey = missenaExt.ApiKey + missenaInternalParams.Placement = missenaExt.Placement + missenaInternalParams.TestMode = missenaExt.TestMode + + newHttpRequest, err := a.makeRequest(missenaInternalParams, requestInfo, imp.ID, request) + if err != nil { + errors = append(errors, err) + continue + } + + httpRequests = append(httpRequests, newHttpRequest) + + break + } + + return httpRequests, errors +} + +func readGDPR(request *openrtb2.BidRequest) (bool, string) { + consentString := "" + if request.User != nil { + var extUser openrtb_ext.ExtUser + if err := json.Unmarshal(request.User.Ext, &extUser); err == nil { + consentString = extUser.Consent + } + } + gdprApplies := false + var extRegs openrtb_ext.ExtRegs + if request.Regs != nil { + if err := json.Unmarshal(request.Regs.Ext, &extRegs); err == nil { + if extRegs.GDPR != nil { + gdprApplies = (*extRegs.GDPR == 1) + } + } + } + return gdprApplies, consentString +} + +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 missenaResponse MissenaBidServerResponse + if err := json.Unmarshal(responseData.Body, &missenaResponse); err != nil { + return nil, []error{err} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) + bidResponse.Currency = missenaResponse.Currency + + responseBid := &openrtb2.Bid{ + ID: request.ID, + Price: float64(missenaResponse.Cpm), + ImpID: request.Imp[0].ID, + AdM: missenaResponse.Ad, + CrID: missenaResponse.RequestId, + } + + b := &adapters.TypedBid{ + Bid: responseBid, + BidType: openrtb_ext.BidTypeBanner, + } + + bidResponse.Bids = append(bidResponse.Bids, b) + + return bidResponse, nil +} diff --git a/adapters/missena/missena_test.go b/adapters/missena/missena_test.go new file mode 100644 index 00000000000..2b13bf085db --- /dev/null +++ b/adapters/missena/missena_test.go @@ -0,0 +1,21 @@ +package missena + +import ( + "testing" + + "github.com/prebid/prebid-server/v2/adapters/adapterstest" + "github.com/prebid/prebid-server/v2/config" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderMissena, config.Adapter{ + Endpoint: "http://example.com/"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "missenatest", bidder) +} diff --git a/adapters/missena/missenatest/exemplary/multiple-imps.json b/adapters/missena/missenatest/exemplary/multiple-imps.json new file mode 100644 index 00000000000..5b83f19ccd0 --- /dev/null +++ b/adapters/missena/missenatest/exemplary/multiple-imps.json @@ -0,0 +1,129 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ip": "123.123.123.123", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id-1", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement-1", + "test": "1" + } + } + }, + { + "id": "test-imp-id-2", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement-2", + "test": "1" + } + } + }, + { + "id": "test-imp-id-3", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": "abc" + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement-1", + "test": "1" + }, + "impIDs":["test-imp-id-1"] + }, + "mockResponse": { + "status": 200, + "body": { + "ad": "
test ad
", + "cpm": 1.5, + "currency": "EUR", + "requestId": "test-request-id" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id-1", + "price": 1.5, + "adm": "
test ad
", + "crid": "test-request-id" + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/exemplary/simple-banner-ipv6.json b/adapters/missena/missenatest/exemplary/simple-banner-ipv6.json new file mode 100644 index 00000000000..ea240f82e09 --- /dev/null +++ b/adapters/missena/missenatest/exemplary/simple-banner-ipv6.json @@ -0,0 +1,105 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ipv6": "2001:0000:130F:0000:0000:09C0:876A:130B", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement", + "test": "1" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "2001:0000:130F:0000:0000:09C0:876A:130B" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement", + "test": "1" + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "ad": "
test ad
", + "cpm": 1.5, + "currency": "EUR", + "requestId": "test-request-id" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1.5, + "adm": "
test ad
", + "crid": "test-request-id" + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/exemplary/simple-banner.json b/adapters/missena/missenatest/exemplary/simple-banner.json new file mode 100644 index 00000000000..74ff3abfd57 --- /dev/null +++ b/adapters/missena/missenatest/exemplary/simple-banner.json @@ -0,0 +1,105 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ip": "123.123.123.123", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement", + "test": "1" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement", + "test": "1" + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "ad": "
test ad
", + "cpm": 1.5, + "currency": "EUR", + "requestId": "test-request-id" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1.5, + "adm": "
test ad
", + "crid": "test-request-id" + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/exemplary/valid-imp-error-imp.json b/adapters/missena/missenatest/exemplary/valid-imp-error-imp.json new file mode 100644 index 00000000000..61be3f78c4c --- /dev/null +++ b/adapters/missena/missenatest/exemplary/valid-imp-error-imp.json @@ -0,0 +1,129 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ip": "123.123.123.123", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id-1", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement-1", + "test": "1" + } + } + }, + { + "id": "test-imp-id-2", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement-2", + "test": "1" + } + } + }, + { + "id": "test-imp-id-3", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": "abc" + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement-1", + "test": "1" + }, + "impIDs": ["test-imp-id-1"] + }, + "mockResponse": { + "status": 200, + "body": { + "ad": "
test ad
", + "cpm": 1.5, + "currency": "EUR", + "requestId": "test-request-id" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id-1", + "price": 1.5, + "adm": "
test ad
", + "crid": "test-request-id" + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/supplemental/error-ext-bidder.json b/adapters/missena/missenatest/supplemental/error-ext-bidder.json new file mode 100644 index 00000000000..fdc08f4704b --- /dev/null +++ b/adapters/missena/missenatest/supplemental/error-ext-bidder.json @@ -0,0 +1,25 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://publisher.com/url" + }, + "user": { + "buyeruid": "1" + }, + "imp": [ + { + "id": "test-imp-id", + "ext": { + "bidder": "abc" + } + } + ] + }, + "expectedMakeRequestsErrors": [ + { + "value": "Error parsing missenaExt parameters", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/supplemental/error-imp-ext.json b/adapters/missena/missenatest/supplemental/error-imp-ext.json new file mode 100644 index 00000000000..3905efa6bab --- /dev/null +++ b/adapters/missena/missenatest/supplemental/error-imp-ext.json @@ -0,0 +1,23 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://publisher.com/url" + }, + "user": { + "buyeruid": "1" + }, + "imp": [ + { + "id": "test-imp-id", + "ext": "error" + } + ] + }, + "expectedMakeRequestsErrors": [ + { + "value": "Error parsing bidderExt object", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/supplemental/status-204.json b/adapters/missena/missenatest/supplemental/status-204.json new file mode 100644 index 00000000000..59070ab4ecb --- /dev/null +++ b/adapters/missena/missenatest/supplemental/status-204.json @@ -0,0 +1,83 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ip": "123.123.123.123", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement", + "test": "1" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement", + "test": "1" + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 204 + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/missena/missenatest/supplemental/status-400.json b/adapters/missena/missenatest/supplemental/status-400.json new file mode 100644 index 00000000000..23a153208e3 --- /dev/null +++ b/adapters/missena/missenatest/supplemental/status-400.json @@ -0,0 +1,89 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ip": "123.123.123.123", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement", + "test": "1" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement", + "test": "1" + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 400, + "body": "Bad request from publisher." + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.", + "comparison": "literal" + } + ] + } \ No newline at end of file diff --git a/adapters/missena/missenatest/supplemental/status-not-200.json b/adapters/missena/missenatest/supplemental/status-not-200.json new file mode 100644 index 00000000000..8c913791fc3 --- /dev/null +++ b/adapters/missena/missenatest/supplemental/status-not-200.json @@ -0,0 +1,89 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "tmax": 500, + "at": 1, + "cur": [ + "EUR" + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "ext": { + "consent": "CO-X2XiO_eyUoAsAxBFRBECsA" + } + }, + "device": { + "ip": "123.123.123.123", + "ua": "test-user-agent" + }, + "site": { + "page": "https://example.com/page", + "domain": "example.com" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "h": 50, + "w": 320 + }, + "ext": { + "bidder": { + "apiKey": "test-api-key", + "placement": "test-placement", + "test": "1" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/?t=test-api-key", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ], + "User-Agent": [ + "test-user-agent" + ], + "X-Forwarded-For": [ + "123.123.123.123" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "body": { + "request_id": "test-request-id", + "timeout": 2000, + "referer": "https://example.com/page", + "referer_canonical": "example.com", + "consent_string": "CO-X2XiO_eyUoAsAxBFRBECsA", + "consent_required": true, + "placement": "test-placement", + "test": "1" + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 404, + "body": {} + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 404. Run with request.debug = 1 for more info.", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/missena/params_test.go b/adapters/missena/params_test.go new file mode 100644 index 00000000000..e76b80b694f --- /dev/null +++ b/adapters/missena/params_test.go @@ -0,0 +1,50 @@ +package missena + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v2/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.BidderMissena, 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.BidderMissena, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + } +} + +var validParams = []string{ + `{"apiKey": "PA-123456"}`, + `{"apiKey": "PA-123456", "placement": "sticky"}`, + `{"apiKey": "PA-123456", "test": "native"}`, +} + +var invalidParams = []string{ + `{"apiKey": ""}`, + `{"apiKey": 42}`, + `{"placement": 111}`, + `{"placement": "sticky"}`, + `{"apiKey": "PA-123456", "placement": 111}`, + `{"test": "native"}`, + `{"apiKey": "PA-123456", "test": 111}`, +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 88948460aff..7f1496810e2 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -138,6 +138,7 @@ import ( "github.com/prebid/prebid-server/v2/adapters/mgid" "github.com/prebid/prebid-server/v2/adapters/mgidX" "github.com/prebid/prebid-server/v2/adapters/minutemedia" + "github.com/prebid/prebid-server/v2/adapters/missena" "github.com/prebid/prebid-server/v2/adapters/mobfoxpb" "github.com/prebid/prebid-server/v2/adapters/mobilefuse" "github.com/prebid/prebid-server/v2/adapters/motorik" @@ -369,6 +370,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderMgid: mgid.Builder, openrtb_ext.BidderMgidX: mgidX.Builder, openrtb_ext.BidderMinuteMedia: minutemedia.Builder, + openrtb_ext.BidderMissena: missena.Builder, openrtb_ext.BidderMobfoxpb: mobfoxpb.Builder, openrtb_ext.BidderMobileFuse: mobilefuse.Builder, openrtb_ext.BidderMotorik: motorik.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 522e2490da1..f7706ce5c25 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -156,6 +156,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderMgid, BidderMgidX, BidderMinuteMedia, + BidderMissena, BidderMobfoxpb, BidderMobileFuse, BidderMotorik, @@ -484,6 +485,7 @@ const ( BidderMgid BidderName = "mgid" BidderMgidX BidderName = "mgidX" BidderMinuteMedia BidderName = "minutemedia" + BidderMissena BidderName = "missena" BidderMobfoxpb BidderName = "mobfoxpb" BidderMobileFuse BidderName = "mobilefuse" BidderMotorik BidderName = "motorik" diff --git a/openrtb_ext/imp_missena.go b/openrtb_ext/imp_missena.go new file mode 100644 index 00000000000..3e341957123 --- /dev/null +++ b/openrtb_ext/imp_missena.go @@ -0,0 +1,7 @@ +package openrtb_ext + +type ExtImpMissena struct { + ApiKey string `json:"apiKey"` + Placement string `json:"placement"` + TestMode string `json:"test"` +} diff --git a/static/bidder-info/missena.yaml b/static/bidder-info/missena.yaml new file mode 100644 index 00000000000..47f089b9c5a --- /dev/null +++ b/static/bidder-info/missena.yaml @@ -0,0 +1,16 @@ +endpoint: https://bid.missena.io/ +maintainer: + email: prebid@missena.com +gvlVendorID: 687 +modifyingVastXmlAllowed: true +capabilities: + app: + mediaTypes: + - banner + site: + mediaTypes: + - banner +userSync: + iframe: + url: https://sync.missena.io/iframe?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}} + userMacro: $UID \ No newline at end of file diff --git a/static/bidder-params/missena.json b/static/bidder-params/missena.json new file mode 100644 index 00000000000..c9e20e5a828 --- /dev/null +++ b/static/bidder-params/missena.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Missena Adapter Params", + "description": "A schema which validates params accepted by the Missena adapter", + "type": "object", + "properties": { + "apiKey": { + "type": "string", + "description": "API Key", + "minLength": 1 + }, + "placement": { + "type": "string", + "description": "Placement Type (Sticky, Header, ...)" + }, + "test": { + "type": "string", + "description": "Test Mode" + } + }, + "required": [ + "apiKey" + ] +} \ No newline at end of file From 64584f60f0922ef9b285089469d667424e33d395 Mon Sep 17 00:00:00 2001 From: Brian Sardo <1168933+bsardo@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:52:25 +0000 Subject: [PATCH 03/22] Refactor: Remove getAuctionBidderRequests (#3957) --- exchange/utils.go | 147 ++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 78 deletions(-) diff --git a/exchange/utils.go b/exchange/utils.go index f56a88151d9..0ba1b3e831d 100644 --- a/exchange/utils.go +++ b/exchange/utils.go @@ -81,9 +81,76 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, return } - var allBidderRequests []BidderRequest + allBidderRequests := make([]BidderRequest, 0, len(impsByBidder)) var allBidderRequestErrs []error - allBidderRequests, allBidderRequestErrs = getAuctionBidderRequests(auctionReq, requestExt, rs.bidderToSyncerKey, impsByBidder, requestAliases, rs.hostSChainNode) + explicitBuyerUIDs, err := extractBuyerUIDs(req.BidRequest.User) + if err != nil { + errs = []error{err} + return + } + + bidderParamsInReqExt, err := ExtractReqExtBidderParamsMap(req.BidRequest) + if err != nil { + errs = []error{err} + return + } + + sChainWriter, err := schain.NewSChainWriter(requestExt, rs.hostSChainNode) + if err != nil { + errs = []error{err} + return + } + + lowerCaseExplicitBuyerUIDs := make(map[string]string) + for bidder, uid := range explicitBuyerUIDs { + lowerKey := strings.ToLower(bidder) + lowerCaseExplicitBuyerUIDs[lowerKey] = uid + } + + for bidder, imps := range impsByBidder { + coreBidder, isRequestAlias := resolveBidder(bidder, requestAliases) + + reqCopy := *req.BidRequest + reqCopy.Imp = imps + + sChainWriter.Write(&reqCopy, bidder) + + reqCopy.Ext, err = buildRequestExtForBidder(bidder, req.BidRequest.Ext, requestExt, bidderParamsInReqExt, auctionReq.Account.AlternateBidderCodes) + if err != nil { + errs = append(errs, err) + continue + } + + if err := removeUnpermissionedEids(&reqCopy, bidder, requestExt); err != nil { + errs = append(errs, fmt.Errorf("unable to enforce request.ext.prebid.data.eidpermissions because %v", err)) + continue + } + + bidderRequest := BidderRequest{ + BidderName: openrtb_ext.BidderName(bidder), + BidderCoreName: coreBidder, + IsRequestAlias: isRequestAlias, + BidRequest: &reqCopy, + BidderLabels: metrics.AdapterLabels{ + Source: auctionReq.LegacyLabels.Source, + RType: auctionReq.LegacyLabels.RType, + Adapter: coreBidder, + PubID: auctionReq.LegacyLabels.PubID, + CookieFlag: auctionReq.LegacyLabels.CookieFlag, + AdapterBids: metrics.AdapterBidPresent, + }, + } + + syncerKey := rs.bidderToSyncerKey[string(coreBidder)] + if hadSync := prepareUser(&reqCopy, bidder, syncerKey, lowerCaseExplicitBuyerUIDs, auctionReq.UserSyncs); !hadSync && req.BidRequest.App == nil { + bidderRequest.BidderLabels.CookieFlag = metrics.CookieFlagNo + } else { + bidderRequest.BidderLabels.CookieFlag = metrics.CookieFlagYes + } + + allBidderRequests = append(allBidderRequests, bidderRequest) + } + if allBidderRequestErrs != nil { errs = append(errs, allBidderRequestErrs...) } @@ -322,82 +389,6 @@ func ExtractReqExtBidderParamsMap(bidRequest *openrtb2.BidRequest) (map[string]j return bidderParams, nil } -func getAuctionBidderRequests(auctionRequest AuctionRequest, - requestExt *openrtb_ext.ExtRequest, - bidderToSyncerKey map[string]string, - impsByBidder map[string][]openrtb2.Imp, - requestAliases map[string]string, - hostSChainNode *openrtb2.SupplyChainNode) ([]BidderRequest, []error) { - - bidderRequests := make([]BidderRequest, 0, len(impsByBidder)) - req := auctionRequest.BidRequestWrapper - explicitBuyerUIDs, err := extractBuyerUIDs(req.BidRequest.User) - if err != nil { - return nil, []error{err} - } - - bidderParamsInReqExt, err := ExtractReqExtBidderParamsMap(req.BidRequest) - if err != nil { - return nil, []error{err} - } - - sChainWriter, err := schain.NewSChainWriter(requestExt, hostSChainNode) - if err != nil { - return nil, []error{err} - } - - lowerCaseExplicitBuyerUIDs := make(map[string]string) - for bidder, uid := range explicitBuyerUIDs { - lowerKey := strings.ToLower(bidder) - lowerCaseExplicitBuyerUIDs[lowerKey] = uid - } - - var errs []error - for bidder, imps := range impsByBidder { - coreBidder, isRequestAlias := resolveBidder(bidder, requestAliases) - - reqCopy := *req.BidRequest - reqCopy.Imp = imps - - sChainWriter.Write(&reqCopy, bidder) - - reqCopy.Ext, err = buildRequestExtForBidder(bidder, req.BidRequest.Ext, requestExt, bidderParamsInReqExt, auctionRequest.Account.AlternateBidderCodes) - if err != nil { - return nil, []error{err} - } - - if err := removeUnpermissionedEids(&reqCopy, bidder, requestExt); err != nil { - errs = append(errs, fmt.Errorf("unable to enforce request.ext.prebid.data.eidpermissions because %v", err)) - continue - } - - bidderRequest := BidderRequest{ - BidderName: openrtb_ext.BidderName(bidder), - BidderCoreName: coreBidder, - IsRequestAlias: isRequestAlias, - BidRequest: &reqCopy, - BidderLabels: metrics.AdapterLabels{ - Source: auctionRequest.LegacyLabels.Source, - RType: auctionRequest.LegacyLabels.RType, - Adapter: coreBidder, - PubID: auctionRequest.LegacyLabels.PubID, - CookieFlag: auctionRequest.LegacyLabels.CookieFlag, - AdapterBids: metrics.AdapterBidPresent, - }, - } - - syncerKey := bidderToSyncerKey[string(coreBidder)] - if hadSync := prepareUser(&reqCopy, bidder, syncerKey, lowerCaseExplicitBuyerUIDs, auctionRequest.UserSyncs); !hadSync && req.BidRequest.App == nil { - bidderRequest.BidderLabels.CookieFlag = metrics.CookieFlagNo - } else { - bidderRequest.BidderLabels.CookieFlag = metrics.CookieFlagYes - } - - bidderRequests = append(bidderRequests, bidderRequest) - } - return bidderRequests, errs -} - func buildRequestExtForBidder(bidder string, requestExt json.RawMessage, requestExtParsed *openrtb_ext.ExtRequest, bidderParamsInReqExt map[string]json.RawMessage, cfgABC *openrtb_ext.ExtAlternateBidderCodes) (json.RawMessage, error) { // Resolve alternatebiddercode for current bidder var reqABC *openrtb_ext.ExtAlternateBidderCodes From 87d4412b6c8e01a011c8b258274a87c37c7760bc Mon Sep 17 00:00:00 2001 From: Brian Sardo <1168933+bsardo@users.noreply.github.com> Date: Wed, 9 Oct 2024 19:08:14 +0000 Subject: [PATCH 04/22] Refactor: Move privacy init up (#3958) --- exchange/utils.go | 110 +++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/exchange/utils.go b/exchange/utils.go index 0ba1b3e831d..2805f32a08a 100644 --- a/exchange/utils.go +++ b/exchange/utils.go @@ -81,13 +81,16 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, return } - allBidderRequests := make([]BidderRequest, 0, len(impsByBidder)) - var allBidderRequestErrs []error explicitBuyerUIDs, err := extractBuyerUIDs(req.BidRequest.User) if err != nil { errs = []error{err} return } + lowerCaseExplicitBuyerUIDs := make(map[string]string) + for bidder, uid := range explicitBuyerUIDs { + lowerKey := strings.ToLower(bidder) + lowerCaseExplicitBuyerUIDs[lowerKey] = uid + } bidderParamsInReqExt, err := ExtractReqExtBidderParamsMap(req.BidRequest) if err != nil { @@ -101,12 +104,58 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, return } - lowerCaseExplicitBuyerUIDs := make(map[string]string) - for bidder, uid := range explicitBuyerUIDs { - lowerKey := strings.ToLower(bidder) - lowerCaseExplicitBuyerUIDs[lowerKey] = uid + var gpp gpplib.GppContainer + if req.BidRequest.Regs != nil && len(req.BidRequest.Regs.GPP) > 0 { + var gppErrs []error + gpp, gppErrs = gpplib.Parse(req.BidRequest.Regs.GPP) + if len(gppErrs) > 0 { + errs = append(errs, gppErrs[0]) + } + } + + consent, err := getConsent(req, gpp) + if err != nil { + errs = append(errs, err) + } + + ccpaEnforcer, err := extractCCPA(req.BidRequest, rs.privacyConfig, &auctionReq.Account, requestAliases, channelTypeMap[auctionReq.LegacyLabels.RType], gpp) + if err != nil { + errs = append(errs, err) + } + + lmtEnforcer := extractLMT(req.BidRequest, rs.privacyConfig) + + // request level privacy policies + coppa := req.BidRequest.Regs != nil && req.BidRequest.Regs.COPPA == 1 + lmt := lmtEnforcer.ShouldEnforce(unknownBidder) + + privacyLabels.CCPAProvided = ccpaEnforcer.CanEnforce() + privacyLabels.CCPAEnforced = ccpaEnforcer.ShouldEnforce(unknownBidder) + privacyLabels.COPPAEnforced = coppa + privacyLabels.LMTEnforced = lmt + + var gdprPerms gdpr.Permissions = &gdpr.AlwaysAllow{} + + if gdprEnforced { + privacyLabels.GDPREnforced = true + parsedConsent, err := vendorconsent.ParseString(consent) + if err == nil { + version := int(parsedConsent.Version()) + privacyLabels.GDPRTCFVersion = metrics.TCFVersionToValue(version) + } + + gdprRequestInfo := gdpr.RequestInfo{ + AliasGVLIDs: requestAliasesGVLIDs, + Consent: consent, + GDPRSignal: gdprSignal, + PublisherID: auctionReq.LegacyLabels.PubID, + } + gdprPerms = rs.gdprPermsBuilder(auctionReq.TCF2Config, gdprRequestInfo) } + allBidderRequests := make([]BidderRequest, 0, len(impsByBidder)) + var allBidderRequestErrs []error + for bidder, imps := range impsByBidder { coreBidder, isRequestAlias := resolveBidder(bidder, requestAliases) @@ -159,60 +208,11 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, //this function should be executed after getAuctionBidderRequests allBidderRequests = mergeBidderRequests(allBidderRequests, bidderNameToBidderReq) - var gpp gpplib.GppContainer - if req.BidRequest.Regs != nil && len(req.BidRequest.Regs.GPP) > 0 { - var gppErrs []error - gpp, gppErrs = gpplib.Parse(req.BidRequest.Regs.GPP) - if len(gppErrs) > 0 { - errs = append(errs, gppErrs[0]) - } - } - if auctionReq.Account.PriceFloors.IsAdjustForBidAdjustmentEnabled() { //Apply BidAdjustmentFactor to imp.BidFloor applyBidAdjustmentToFloor(allBidderRequests, bidAdjustmentFactors) } - consent, err := getConsent(req, gpp) - if err != nil { - errs = append(errs, err) - } - - ccpaEnforcer, err := extractCCPA(req.BidRequest, rs.privacyConfig, &auctionReq.Account, requestAliases, channelTypeMap[auctionReq.LegacyLabels.RType], gpp) - if err != nil { - errs = append(errs, err) - } - - lmtEnforcer := extractLMT(req.BidRequest, rs.privacyConfig) - - // request level privacy policies - coppa := req.BidRequest.Regs != nil && req.BidRequest.Regs.COPPA == 1 - lmt := lmtEnforcer.ShouldEnforce(unknownBidder) - - privacyLabels.CCPAProvided = ccpaEnforcer.CanEnforce() - privacyLabels.CCPAEnforced = ccpaEnforcer.ShouldEnforce(unknownBidder) - privacyLabels.COPPAEnforced = coppa - privacyLabels.LMTEnforced = lmt - - var gdprPerms gdpr.Permissions = &gdpr.AlwaysAllow{} - - if gdprEnforced { - privacyLabels.GDPREnforced = true - parsedConsent, err := vendorconsent.ParseString(consent) - if err == nil { - version := int(parsedConsent.Version()) - privacyLabels.GDPRTCFVersion = metrics.TCFVersionToValue(version) - } - - gdprRequestInfo := gdpr.RequestInfo{ - AliasGVLIDs: requestAliasesGVLIDs, - Consent: consent, - GDPRSignal: gdprSignal, - PublisherID: auctionReq.LegacyLabels.PubID, - } - gdprPerms = rs.gdprPermsBuilder(auctionReq.TCF2Config, gdprRequestInfo) - } - allowedBidderRequests = make([]BidderRequest, 0, len(allBidderRequests)) for _, bidderRequest := range allBidderRequests { From 9bb9b3db2135b0085e8b1f3608eb1da73871e6b7 Mon Sep 17 00:00:00 2001 From: bhainesnexxen <146981622+bhainesnexxen@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:09:33 -0700 Subject: [PATCH 05/22] Unruly: Indicate Support for OpenRTB 2.6 (#3984) --- static/bidder-info/unruly.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/static/bidder-info/unruly.yaml b/static/bidder-info/unruly.yaml index 6389f831a64..62f03dec84d 100644 --- a/static/bidder-info/unruly.yaml +++ b/static/bidder-info/unruly.yaml @@ -1,7 +1,13 @@ endpoint: "https://targeting.unrulymedia.com/unruly_prebid_server" +endpointCompression: gzip +geoscope: + - global maintainer: email: "prebidsupport@unrulygroup.com" gvlVendorID: 36 +openrtb: + version: 2.6 + gpp-supported: true capabilities: app: mediaTypes: @@ -14,4 +20,4 @@ capabilities: userSync: redirect: url: "https://sync.1rx.io/usersync2/rmphb?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}" - userMacro: "[RX_UUID]" \ No newline at end of file + userMacro: "[RX_UUID]" From c37951a3be2494623bffbed352137eed98bf7b1b Mon Sep 17 00:00:00 2001 From: ym-winston <46379634+ym-winston@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:18:54 -0400 Subject: [PATCH 06/22] update yieldmo.yaml to indicate support for ortb 2.6 (#3968) --- static/bidder-info/yieldmo.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/static/bidder-info/yieldmo.yaml b/static/bidder-info/yieldmo.yaml index 02ab8721a16..17b25ecbbf1 100644 --- a/static/bidder-info/yieldmo.yaml +++ b/static/bidder-info/yieldmo.yaml @@ -2,6 +2,8 @@ endpoint: "https://ads.yieldmo.com/exchange/prebid-server" maintainer: email: "prebid@yieldmo.com" gvlVendorID: 173 +openrtb: + version: 2.6 capabilities: app: mediaTypes: From 5fcbbbfb17d4029bf60f03c7919490dfcdd98874 Mon Sep 17 00:00:00 2001 From: Patrick Loughrey Date: Tue, 15 Oct 2024 15:19:47 -0400 Subject: [PATCH 07/22] Triplelift: Adding flag for 2.6 support (#3966) --- static/bidder-info/triplelift.yaml | 8 +++++--- static/bidder-info/triplelift_native.yaml | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/static/bidder-info/triplelift.yaml b/static/bidder-info/triplelift.yaml index 605bcc71e6e..79a8951680f 100644 --- a/static/bidder-info/triplelift.yaml +++ b/static/bidder-info/triplelift.yaml @@ -12,9 +12,10 @@ capabilities: - banner - video userSync: - # Triplelift supports user syncing but requires configuration by the host as the RedirectURL domain must be allowlisted. - # Contact this bidder directly at the email address above to ask about enabling user sync. - # + # Triplelift supports user syncing but requires configuration by the host as the RedirectURL domain must be allowlisted. + # If you are a publisher hosting your own Prebid Server, contact this bidder directly at the email address above to ask about enabling user sync. + # If you are a Prebid Server Host, please have your publisher contact the bidder. + # iframe: url: "https://eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}" userMacro: $UID @@ -23,4 +24,5 @@ userSync: userMacro: "$UID" endpointCompression: "GZIP" openrtb: + version: 2.6 gpp-supported: true \ No newline at end of file diff --git a/static/bidder-info/triplelift_native.yaml b/static/bidder-info/triplelift_native.yaml index ff93b544c4c..c5e08152692 100644 --- a/static/bidder-info/triplelift_native.yaml +++ b/static/bidder-info/triplelift_native.yaml @@ -12,8 +12,9 @@ capabilities: mediaTypes: - native userSync: - # Triplelift supports user syncing but requires configuration by the host as the RedirectURL domain must be allowlisted. - # Contact this bidder directly at the email address above to ask about enabling user sync. + # Triplelift supports user syncing but requires configuration by the host as the RedirectURL domain must be allowlisted. + # If you are a publisher hosting your own Prebid Server, contact this bidder directly at the email address above to ask about enabling user sync. + # If you are a Prebid Server Host, please have your publisher contact the bidder. # iframe: url: "https://eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}" @@ -22,4 +23,5 @@ userSync: url: "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}" userMacro: "$UID" openrtb: + version: 2.6 gpp-supported: true \ No newline at end of file From cbe987664b8b36a63620ac9fd88ef3a4731c1892 Mon Sep 17 00:00:00 2001 From: Irakli Gotsiridze Date: Tue, 15 Oct 2024 23:30:17 +0400 Subject: [PATCH 08/22] enable gzip (#3946) --- static/bidder-info/sovrn.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/static/bidder-info/sovrn.yaml b/static/bidder-info/sovrn.yaml index 62d74152b0b..fad1850d4b3 100644 --- a/static/bidder-info/sovrn.yaml +++ b/static/bidder-info/sovrn.yaml @@ -1,6 +1,7 @@ endpoint: "http://pbs.lijit.com/rtb/bid?src=prebid_server" maintainer: email: "sovrnoss@sovrn.com" +endpointCompression: gzip gvlVendorID: 13 modifyingVastXmlAllowed: true capabilities: From b56923c28d20f05cc0b8d4d0a340233b4ed03840 Mon Sep 17 00:00:00 2001 From: Piotr Jaworski <109736938+piotrj-rtbh@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:49:39 +0200 Subject: [PATCH 09/22] RTB House: Resolve AUCTION_PRICE macro (#3901) --- adapters/rtbhouse/rtbhouse.go | 12 ++- .../exemplary/banner-resolve-macros.json | 87 +++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 adapters/rtbhouse/rtbhousetest/exemplary/banner-resolve-macros.json diff --git a/adapters/rtbhouse/rtbhouse.go b/adapters/rtbhouse/rtbhouse.go index bd0d892b996..daca87bc961 100644 --- a/adapters/rtbhouse/rtbhouse.go +++ b/adapters/rtbhouse/rtbhouse.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "strconv" "strings" "github.com/buger/jsonparser" @@ -161,8 +162,9 @@ func (adapter *RTBHouseAdapter) MakeBids( var typedBid *adapters.TypedBid for _, seatBid := range openRTBBidderResponse.SeatBid { for _, bid := range seatBid.Bid { - bid := bid // pin! -> https://github.com/kyoh86/scopelint#whats-this + bid := bid bidType, err := getMediaTypeForBid(bid) + resolveMacros(&bid) if err != nil { errs = append(errs, err) continue @@ -222,3 +224,11 @@ func getNativeAdm(adm string) (string, error) { return adm, nil } + +func resolveMacros(bid *openrtb2.Bid) { + if bid != nil { + price := strconv.FormatFloat(bid.Price, 'f', -1, 64) + bid.NURL = strings.Replace(bid.NURL, "${AUCTION_PRICE}", price, -1) + bid.AdM = strings.Replace(bid.AdM, "${AUCTION_PRICE}", price, -1) + } +} diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/banner-resolve-macros.json b/adapters/rtbhouse/rtbhousetest/exemplary/banner-resolve-macros.json new file mode 100644 index 00000000000..eaa3965040e --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/exemplary/banner-resolve-macros.json @@ -0,0 +1,87 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://good.site/url" + }, + "imp": [{ + "id": "test-imp-id", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }] + }, + "ext": { + "bidder": {} + } + }] + }, + + "httpCalls": [{ + "expectedRequest": { + "uri": "http://localhost/prebid_server", + "body": { + "id": "test-request-id", + "cur": ["USD"], + "site": { + "page": "https://good.site/url" + }, + "imp": [{ + "id": "test-imp-id", + "banner": { + "format": [{ + "w": 300, + "h": 250 + }] + }, + "ext": { + "bidder": {} + } + }] + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [{ + "seat": "rtbhouse", + "bid": [{ + "id": "randomid", + "impid": "test-imp-id", + "price": 0.500000, + "adid": "12345678", + "adm": "", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }] + }], + "cur": "USD" + } + } + }], + + "expectedBidResponses": [{ + "currency": "USD", + "bids": [{ + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 0.5, + "adm": "", + "adid": "12345678", + "cid": "987", + "crid": "12345678", + "w": 300, + "h": 250, + "mtype": 1 + }, + "type": "banner" + }] + }] +} From 8134328c03de3b8d4618c027dd6caf1c063a00a6 Mon Sep 17 00:00:00 2001 From: Boris Yu Date: Wed, 16 Oct 2024 21:08:50 +0300 Subject: [PATCH 10/22] Displayio: Make imp.bidfloor optional (#3959) --- adapters/displayio/displayio.go | 15 ++------ .../supplemental/missing-bidfloor.json | 35 ------------------- 2 files changed, 3 insertions(+), 47 deletions(-) delete mode 100644 adapters/displayio/displayiotest/supplemental/missing-bidfloor.json diff --git a/adapters/displayio/displayio.go b/adapters/displayio/displayio.go index a3af7c9614f..b54998553b3 100644 --- a/adapters/displayio/displayio.go +++ b/adapters/displayio/displayio.go @@ -37,18 +37,9 @@ func (adapter *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo * for _, impression := range request.Imp { var requestExt map[string]interface{} - if impression.BidFloor == 0 { - errs = append(errs, &errortypes.BadInput{ - Message: "BidFloor should be defined", - }) - continue - } - - if impression.BidFloorCur == "" { + if impression.BidFloorCur == "" || impression.BidFloor == 0 { impression.BidFloorCur = "USD" - } - - if impression.BidFloorCur != "USD" { + } else if impression.BidFloorCur != "USD" { convertedValue, err := requestInfo.ConvertCurrency(impression.BidFloor, impression.BidFloorCur, "USD") if err != nil { @@ -56,8 +47,8 @@ func (adapter *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo * continue } - impression.BidFloorCur = "USD" impression.BidFloor = convertedValue + impression.BidFloorCur = "USD" } if len(impression.Ext) == 0 { diff --git a/adapters/displayio/displayiotest/supplemental/missing-bidfloor.json b/adapters/displayio/displayiotest/supplemental/missing-bidfloor.json deleted file mode 100644 index d3fe15778ff..00000000000 --- a/adapters/displayio/displayiotest/supplemental/missing-bidfloor.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "mockBidRequest": { - "id": "testid", - "imp": [ - { - "id": "testimpid", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - }, - { - "w": 320, - "h": 50 - } - ] - }, - "ext": { - "bidder": { - "placementId": "1101", - "inventoryId": "1101", - "publisherId": "101" - } - } - } - ] - }, - "expectedMakeRequestsErrors": [ - { - "value": "BidFloor should be defined", - "comparison": "literal" - } - ] -} \ No newline at end of file From 451bc449e09be5aa5310e865bc3904fa92ad3474 Mon Sep 17 00:00:00 2001 From: Bluesea <129151981+blueseasx@users.noreply.github.com> Date: Thu, 17 Oct 2024 03:12:50 +0800 Subject: [PATCH 11/22] BlueSea: Add site capability (#3910) Co-authored-by: prebid-bluesea --- .../blueseatest/exemplary/site-banner.json | 133 ++++++++++++++ .../blueseatest/exemplary/site-native.json | 133 ++++++++++++++ .../blueseatest/exemplary/site-video.json | 163 ++++++++++++++++++ static/bidder-info/bluesea.yaml | 6 + 4 files changed, 435 insertions(+) create mode 100644 adapters/bluesea/blueseatest/exemplary/site-banner.json create mode 100644 adapters/bluesea/blueseatest/exemplary/site-native.json create mode 100644 adapters/bluesea/blueseatest/exemplary/site-video.json diff --git a/adapters/bluesea/blueseatest/exemplary/site-banner.json b/adapters/bluesea/blueseatest/exemplary/site-banner.json new file mode 100644 index 00000000000..b3ca13f8d53 --- /dev/null +++ b/adapters/bluesea/blueseatest/exemplary/site-banner.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "site":{ + "id": "100", + "domain": "test.domain", + "page": "https://test.domain?target=_blank", + "keywords": "fashion" + }, + "imp":[ + { + "id":"1", + "banner":{ + "w":300, + "h":250 + }, + "secure":1, + "ext":{ + "bidder":{ + "pubid":"test-pubid", + "token":"test-pub-token" + } + } + } + ], + "device":{ + "os":"android", + "ua":"Mozilla/5.0 (Linux; Android 8.0.0; SC-04J Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "ip":"101.101.101.101", + "h":1280, + "w":720 + }, + "at":1, + "tmax":1200, + "test":1 + }, + "httpCalls":[ + { + "expectedRequest":{ + "uri":"https://test.prebid.bluesea?pubid=test-pubid&token=test-pub-token", + "body":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "site":{ + "id":"100", + "domain": "test.domain", + "page": "https://test.domain?target=_blank", + "keywords": "fashion" + }, + "imp":[ + { + "id":"1", + "banner":{ + "w":300, + "h":250 + }, + "secure":1, + "ext":{ + "bidder":{ + "pubid":"test-pubid", + "token":"test-pub-token" + } + } + } + ], + "device":{ + "os":"android", + "ua":"Mozilla/5.0 (Linux; Android 8.0.0; SC-04J Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "ip":"101.101.101.101", + "h":1280, + "w":720 + }, + "at":1, + "tmax":1200, + "test":1 + }, + "impIDs":["1"] + }, + "mockResponse":{ + "status":200, + "body":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "seatbid":[ + { + "bid":[ + { + "price":0.01, + "adm":"test-adm", + "impid":"1", + "id":"test-bid-id", + "h":250, + "adomain":[ + "adv.com" + ], + "crid":"test-site-crid", + "w":300, + "ext":{ + "mediatype":"banner" + } + } + ], + "seat":"test-seat" + } + ], + "cur":"USD" + } + } + } + ], + "expectedBidResponses":[ + { + "bids":[ + { + "bid":{ + "price":0.01, + "adm":"test-adm", + "impid":"1", + "id":"test-bid-id", + "h":250, + "adomain":[ + "adv.com" + ], + "crid":"test-site-crid", + "w":300, + "ext":{ + "mediatype":"banner" + } + }, + "type":"banner" + } + ] + } + ] +} diff --git a/adapters/bluesea/blueseatest/exemplary/site-native.json b/adapters/bluesea/blueseatest/exemplary/site-native.json new file mode 100644 index 00000000000..b907ebdbea4 --- /dev/null +++ b/adapters/bluesea/blueseatest/exemplary/site-native.json @@ -0,0 +1,133 @@ +{ + "mockBidRequest":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "site":{ + "id": "100", + "domain": "test.domain", + "page": "https://test.domain?target=_blank", + "keywords": "fashion" + }, + "imp":[ + { + "id":"1", + "native":{ + "request":"{\"ver\":\"1.2\",\"context\":1,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":150}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}},{\"id\":3,\"required\":1,\"data\":{\"type\":2,\"len\":120}}]}", + "ver":"1.2" + }, + "secure":1, + "ext":{ + "bidder":{ + "pubid":"test-pubid", + "token":"test-pub-token" + } + } + } + ], + "device":{ + "os":"android", + "ua":"Mozilla/5.0 (Linux; Android 8.0.0; SC-04J Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "ip":"101.101.101.101", + "h":1280, + "w":720 + }, + "at":1, + "tmax":1200, + "test":1 + }, + "httpCalls":[ + { + "expectedRequest":{ + "uri":"https://test.prebid.bluesea?pubid=test-pubid&token=test-pub-token", + "body":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "site":{ + "id":"100", + "domain": "test.domain", + "page": "https://test.domain?target=_blank", + "keywords": "fashion" + }, + "imp":[ + { + "id":"1", + "native":{ + "request":"{\"ver\":\"1.2\",\"context\":1,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":150}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}},{\"id\":3,\"required\":1,\"data\":{\"type\":2,\"len\":120}}]}", + "ver":"1.2" + }, + "secure":1, + "ext":{ + "bidder":{ + "pubid":"test-pubid", + "token":"test-pub-token" + } + } + } + ], + "device":{ + "os":"android", + "ua":"Mozilla/5.0 (Linux; Android 8.0.0; SC-04J Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "ip":"101.101.101.101", + "h":1280, + "w":720 + }, + "at":1, + "tmax":1200, + "test":1 + }, + "impIDs":["1"] + }, + "mockResponse":{ + "status":200, + "body":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "seatbid":[ + { + "bid":[ + { + "price":0.01, + "adm":"test-native-adm", + "impid":"1", + "id":"test-bid-id", + "h":250, + "adomain":[ + "adv.com" + ], + "crid":"test-site-native-crid", + "w":300, + "ext":{ + "mediatype":"native" + } + } + ], + "seat":"test-seat" + } + ], + "cur":"USD" + } + } + } + ], + "expectedBidResponses":[ + { + "bids":[ + { + "bid":{ + "price":0.01, + "adm":"test-native-adm", + "impid":"1", + "id":"test-bid-id", + "h":250, + "adomain":[ + "adv.com" + ], + "crid":"test-site-native-crid", + "w":300, + "ext":{ + "mediatype":"native" + } + }, + "type":"native" + } + ] + } + ] +} diff --git a/adapters/bluesea/blueseatest/exemplary/site-video.json b/adapters/bluesea/blueseatest/exemplary/site-video.json new file mode 100644 index 00000000000..dd191105cd3 --- /dev/null +++ b/adapters/bluesea/blueseatest/exemplary/site-video.json @@ -0,0 +1,163 @@ +{ + "mockBidRequest":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "site":{ + "id": "100", + "domain": "test.domain", + "page": "https://test.domain?target=_blank", + "keywords": "fashion" + }, + "imp":[ + { + "id":"1", + "video":{ + "mimes":[ + "video/mp4", + "application/javascript", + "video/webm" + ], + "minduration":5, + "maxduration":120, + "protocols":[ + 2, + 3, + 5, + 6 + ], + "pos":7, + "w":320, + "h":480, + "linearity":1 + }, + "secure":1, + "ext":{ + "bidder":{ + "pubid":"test-pubid", + "token":"test-pub-token" + } + } + } + ], + "device":{ + "os":"android", + "ua":"Mozilla/5.0 (Linux; Android 8.0.0; SC-04J Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "ip":"101.101.101.101", + "h":1280, + "w":720 + }, + "at":1, + "tmax":1200, + "test":1 + }, + "httpCalls":[ + { + "expectedRequest":{ + "uri":"https://test.prebid.bluesea?pubid=test-pubid&token=test-pub-token", + "body":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "site":{ + "id":"100", + "domain": "test.domain", + "page": "https://test.domain?target=_blank", + "keywords": "fashion" + }, + "imp":[ + { + "id":"1", + "video":{ + "mimes":[ + "video/mp4", + "application/javascript", + "video/webm" + ], + "minduration":5, + "maxduration":120, + "protocols":[ + 2, + 3, + 5, + 6 + ], + "pos":7, + "w":320, + "h":480, + "linearity":1 + }, + "secure":1, + "ext":{ + "bidder":{ + "pubid":"test-pubid", + "token":"test-pub-token" + } + } + } + ], + "device":{ + "os":"android", + "ua":"Mozilla/5.0 (Linux; Android 8.0.0; SC-04J Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "ip":"101.101.101.101", + "h":1280, + "w":720 + }, + "at":1, + "tmax":1200, + "test":1 + }, + "impIDs":["1"] + }, + "mockResponse":{ + "status":200, + "body":{ + "id":"b655d86c-fdf6-4e68-a1e9-abc223f84a65", + "seatbid":[ + { + "bid":[ + { + "price":0.01, + "adm":"test-vast", + "impid":"1", + "id":"test-bid-id", + "h":480, + "adomain":[ + "adv.com" + ], + "crid":"test-site-crid", + "w":320, + "ext":{ + "mediatype":"video" + } + } + ], + "seat":"test-seat" + } + ], + "cur":"USD" + } + } + } + ], + "expectedBidResponses":[ + { + "bids":[ + { + "bid":{ + "price":0.01, + "adm":"test-vast", + "impid":"1", + "id":"test-bid-id", + "h":480, + "adomain":[ + "adv.com" + ], + "crid":"test-site-crid", + "w":320, + "ext":{ + "mediatype":"video" + } + }, + "type":"video" + } + ] + } + ] +} diff --git a/static/bidder-info/bluesea.yaml b/static/bidder-info/bluesea.yaml index 14667cafd6e..a9a5ca203d6 100644 --- a/static/bidder-info/bluesea.yaml +++ b/static/bidder-info/bluesea.yaml @@ -3,9 +3,15 @@ maintainer: email: prebid@blueseasx.com endpointCompression: gzip modifyingVastXmlAllowed: true +gvlVendorID: 1294 capabilities: app: mediaTypes: - banner - native - video + site: + mediaTypes: + - banner + - native + - video From bcf6491f94c685fefc22f222e96c65a5cdd38344 Mon Sep 17 00:00:00 2001 From: sindhuja-sridharan <148382298+sindhuja-sridharan@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:20:45 -0600 Subject: [PATCH 12/22] GumGum: Declare ORTB 2.6 support (#3985) --- static/bidder-info/gumgum.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/static/bidder-info/gumgum.yaml b/static/bidder-info/gumgum.yaml index f7e782e40df..945acf7ca5c 100644 --- a/static/bidder-info/gumgum.yaml +++ b/static/bidder-info/gumgum.yaml @@ -12,3 +12,6 @@ userSync: url: "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}" userMacro: "" # gumgum appends the user id to end of the redirect url and does not utilize a macro +openrtb: + version: 2.6 + gpp-supported: true \ No newline at end of file From 18f679834a60cdb243afd3b7a17fd10dc020a53f Mon Sep 17 00:00:00 2001 From: Sebastien Boisvert Date: Tue, 22 Oct 2024 15:15:07 -0400 Subject: [PATCH 13/22] Bump Go version to 1.22 in dev containers config (#3983) --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ebf6f614df3..f9bb82598ff 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,7 +6,7 @@ "dockerfile": "Dockerfile", "args": { // Update the VARIANT arg to pick a version of Go - "VARIANT": "1.20", + "VARIANT": "1.22", // Options "INSTALL_NODE": "false", "NODE_VERSION": "lts/*" From 03a4abdf04b3176fcb394ca173fedd1b6beba0ff Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 22 Oct 2024 22:26:45 +0300 Subject: [PATCH 14/22] Sample: Fix prebid js loading bug on sample html page (#3792) --- sample/001_banner/pbjs.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sample/001_banner/pbjs.html b/sample/001_banner/pbjs.html index b02ba95b995..af6ad643eec 100644 --- a/sample/001_banner/pbjs.html +++ b/sample/001_banner/pbjs.html @@ -12,8 +12,8 @@ border-style: solid; } - - + -