diff --git a/adapters/rtbhouse/rtbhouse.go b/adapters/rtbhouse/rtbhouse.go index 9a7e3f4f924..c6445f1f154 100644 --- a/adapters/rtbhouse/rtbhouse.go +++ b/adapters/rtbhouse/rtbhouse.go @@ -21,6 +21,16 @@ const ( BidderCurrency string = "USD" ) +// publisherExtPrebid defines the structure for publisher.ext.prebid used by RTBHouse adapter +type publisherExtPrebid struct { + PublisherId string `json:"publisherId,omitempty"` +} + +// publisherExt defines the structure for publisher.ext used by RTBHouse adapter +type publisherExt struct { + Prebid *publisherExtPrebid `json:"prebid,omitempty"` +} + // RTBHouseAdapter implements the Bidder interface. type RTBHouseAdapter struct { endpoint string @@ -45,14 +55,23 @@ func (adapter *RTBHouseAdapter) MakeRequests( reqCopy := *openRTBRequest reqCopy.Imp = []openrtb2.Imp{} + + var publisherId string + for _, imp := range openRTBRequest.Imp { + rtbhouseExt, err := getImpressionExt(imp) + if err != nil { + return nil, []error{err} + } + + // Extract publisherId from the first impression that has one + if publisherId == "" && rtbhouseExt.PublisherId != "" { + publisherId = rtbhouseExt.PublisherId + } + var bidFloorCur = imp.BidFloorCur var bidFloor = imp.BidFloor if bidFloorCur == "" && bidFloor == 0 { - rtbhouseExt, err := getImpressionExt(imp) - if err != nil { - return nil, []error{err} - } if rtbhouseExt.BidFloor > 0 { bidFloor = rtbhouseExt.BidFloor bidFloorCur = BidderCurrency @@ -90,11 +109,22 @@ func (adapter *RTBHouseAdapter) MakeRequests( } imp.Ext = newImpExt + // Remove PMP from impression + imp.PMP = nil + // Set the CUR of bid to BIDDER_CURRENCY after converting all floors reqCopy.Cur = []string{BidderCurrency} reqCopy.Imp = append(reqCopy.Imp, imp) } + // Set publisher ID in site.publisher.ext.prebid.publisherId or app.publisher.ext.prebid.publisherId if we found one + if publisherId != "" { + if err := setPublisherID(&reqCopy, publisherId); err != nil { + errs = append(errs, err) + return nil, errs + } + } + openRTBRequestJSON, err := json.Marshal(reqCopy) if err != nil { errs = append(errs, err) @@ -115,6 +145,60 @@ func (adapter *RTBHouseAdapter) MakeRequests( return requestsToBidder, errs } +// setPublisherID sets the publisherId in site.publisher.ext.prebid.publisherId or app.publisher.ext.prebid.publisherId +func setPublisherID(request *openrtb2.BidRequest, publisherId string) error { + var publisher *openrtb2.Publisher + if request.Site != nil { + // Create a copy of the site to avoid modifying the original request + siteCopy := *request.Site + request.Site = &siteCopy + publisher = request.Site.Publisher + } else if request.App != nil { + // Create a copy of the app to avoid modifying the original request + appCopy := *request.App + request.App = &appCopy + publisher = request.App.Publisher + } else { + // If neither site nor app exists, create a site object + request.Site = &openrtb2.Site{} + } + + if publisher != nil { + // Create a copy of the publisher to avoid modifying the original request + publisherCopy := *publisher + publisher = &publisherCopy + } else { + publisher = &openrtb2.Publisher{} + } + + // Set publisherId in publisher.ext.prebid.publisherId using local struct + var pubExt publisherExt + if publisher.Ext != nil { + if err := jsonutil.Unmarshal(publisher.Ext, &pubExt); err != nil { + return err + } + } + if pubExt.Prebid == nil { + pubExt.Prebid = &publisherExtPrebid{} + } + pubExt.Prebid.PublisherId = publisherId + + publisherExtJSON, err := jsonutil.Marshal(pubExt) + if err != nil { + return err + } + publisher.Ext = publisherExtJSON + + // Assign the updated publisher back to the appropriate object + if request.Site != nil { + request.Site.Publisher = publisher + } else if request.App != nil { + request.App.Publisher = publisher + } + + return nil +} + func clearAuctionEnvironment(imp *openrtb2.Imp) (json.RawMessage, error) { var objmap map[string]interface{} err := json.Unmarshal(imp.Ext, &objmap) diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/ae-igs-removal.json b/adapters/rtbhouse/rtbhousetest/exemplary/ae-igs-removal.json new file mode 100644 index 00000000000..7cf35414aa0 --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/exemplary/ae-igs-removal.json @@ -0,0 +1,118 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "ae": 1, + "igs": { + "biddable": 1 + }, + "bidder": { + "publisherId": "12345" + }, + "someOtherField": "should-remain" + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://localhost/prebid_server", + "body": { + "id": "test-request-id", + "cur": [ + "USD" + ], + "imp": [ + { + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "12345" + }, + "someOtherField": "should-remain" + }, + "id": "test-imp-id" + } + ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "cur": "USD", + "seatbid": [ + { + "seat": "rtbhouse", + "bid": [ + { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/app-with-publisher.json b/adapters/rtbhouse/rtbhousetest/exemplary/app-with-publisher.json new file mode 100644 index 00000000000..d53ab37f2d5 --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/exemplary/app-with-publisher.json @@ -0,0 +1,118 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "com.example.app", + "name": "Test App" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "app-publisher-123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://localhost/prebid_server", + "body": { + "id": "test-request-id", + "cur": [ + "USD" + ], + "app": { + "bundle": "com.example.app", + "name": "Test App", + "publisher": { + "ext": { + "prebid": { + "publisherId": "app-publisher-123" + } + } + } + }, + "imp": [ + { + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "app-publisher-123" + } + }, + "id": "test-imp-id" + } + ] + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "cur": "USD", + "seatbid": [ + { + "seat": "rtbhouse", + "bid": [ + { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param-without-cur.json b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param-without-cur.json index 9b0f8d3e38b..d31110cb3ef 100644 --- a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param-without-cur.json +++ b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param-without-cur.json @@ -63,6 +63,15 @@ "id": "test-imp-id" } ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + }, "ext": { "prebid": { "currency": { diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param.json b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param.json index c6a82faa574..fd324fb0345 100644 --- a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param.json +++ b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-bidder-param.json @@ -66,6 +66,15 @@ "id": "test-imp-id" } ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + }, "ext": { "prebid": { "currency": { diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-with-cur.json b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-with-cur.json index b0b34a25afe..24cc0822dde 100644 --- a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-with-cur.json +++ b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-with-cur.json @@ -63,6 +63,15 @@ "id": "test-imp-id" } ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + }, "ext": { "prebid": { "currency": { diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-without-cur.json b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-without-cur.json index a6dbcec864a..e579017c079 100644 --- a/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-without-cur.json +++ b/adapters/rtbhouse/rtbhousetest/exemplary/bidfloor-as-impbidfloor-without-cur.json @@ -61,6 +61,15 @@ "id": "test-imp-id" } ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + }, "ext": { "prebid": { "currency": { diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/existing-site-publisher-override.json b/adapters/rtbhouse/rtbhousetest/exemplary/existing-site-publisher-override.json new file mode 100644 index 00000000000..235e2c4a8bb --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/exemplary/existing-site-publisher-override.json @@ -0,0 +1,122 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "https://example.com", + "publisher": { + "id": "existing-publisher", + "name": "Existing Publisher" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "new-publisher-123" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://localhost/prebid_server", + "body": { + "id": "test-request-id", + "cur": [ + "USD" + ], + "site": { + "page": "https://example.com", + "publisher": { + "id": "existing-publisher", + "name": "Existing Publisher", + "ext": { + "prebid": { + "publisherId": "new-publisher-123" + } + } + } + }, + "imp": [ + { + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "new-publisher-123" + } + }, + "id": "test-imp-id" + } + ] + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "cur": "USD", + "seatbid": [ + { + "seat": "rtbhouse", + "bid": [ + { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/multiple-imps-different-publishers.json b/adapters/rtbhouse/rtbhousetest/exemplary/multiple-imps-different-publishers.json new file mode 100644 index 00000000000..3cb44d54220 --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/exemplary/multiple-imps-different-publishers.json @@ -0,0 +1,171 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id-1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "first-publisher" + } + } + }, + { + "id": "test-imp-id-2", + "banner": { + "format": [ + { + "w": 728, + "h": 90 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "second-publisher" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://localhost/prebid_server", + "body": { + "id": "test-request-id", + "cur": [ + "USD" + ], + "imp": [ + { + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "first-publisher" + } + }, + "id": "test-imp-id-1" + }, + { + "banner": { + "format": [ + { + "h": 90, + "w": 728 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "second-publisher" + } + }, + "id": "test-imp-id-2" + } + ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "first-publisher" + } + } + } + } + }, + "impIDs": ["test-imp-id-1", "test-imp-id-2"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "cur": "USD", + "seatbid": [ + { + "seat": "rtbhouse", + "bid": [ + { + "id": "randomid1", + "impid": "test-imp-id-1", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad-1", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }, + { + "id": "randomid2", + "impid": "test-imp-id-2", + "price": 150, + "adid": "87654321", + "adm": "some-test-ad-2", + "cid": "789", + "crid": "87654321", + "h": 90, + "w": 728, + "mtype": 1 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid1", + "impid": "test-imp-id-1", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad-1", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }, + "type": "banner" + }, + { + "bid": { + "id": "randomid2", + "impid": "test-imp-id-2", + "price": 150, + "adid": "87654321", + "adm": "some-test-ad-2", + "cid": "789", + "crid": "87654321", + "h": 90, + "w": 728, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/pmp-removal-test.json b/adapters/rtbhouse/rtbhousetest/exemplary/pmp-removal-test.json new file mode 100644 index 00000000000..0d31ef3d5b7 --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/exemplary/pmp-removal-test.json @@ -0,0 +1,121 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "pmp": { + "deals": [ + { + "id": "deal-id-1", + "bidfloor": 5.00, + "bidfloorcur": "USD" + } + ] + }, + "ext": { + "bidder": { + "publisherId": "12345" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://localhost/prebid_server", + "body": { + "id": "test-request-id", + "cur": [ + "USD" + ], + "imp": [ + { + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ] + }, + "ext": { + "bidder": { + "publisherId": "12345" + } + }, + "id": "test-imp-id" + } + ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "cur": "USD", + "seatbid": [ + { + "seat": "rtbhouse", + "bid": [ + { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "randomid", + "impid": "test-imp-id", + "price": 300, + "adid": "12345678", + "adm": "some-test-ad", + "cid": "987", + "crid": "12345678", + "h": 250, + "w": 300, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/rtbhouse/rtbhousetest/exemplary/two-bidfloors-given-param-and-impbidfloor.json b/adapters/rtbhouse/rtbhousetest/exemplary/two-bidfloors-given-param-and-impbidfloor.json index 7b9ebf9685e..71b95d18db8 100644 --- a/adapters/rtbhouse/rtbhousetest/exemplary/two-bidfloors-given-param-and-impbidfloor.json +++ b/adapters/rtbhouse/rtbhousetest/exemplary/two-bidfloors-given-param-and-impbidfloor.json @@ -65,6 +65,15 @@ "id": "test-imp-id" } ], + "site": { + "publisher": { + "ext": { + "prebid": { + "publisherId": "12345" + } + } + } + }, "ext": { "prebid": { "currency": { diff --git a/adapters/rtbhouse/rtbhousetest/supplemental/malformed-imp-ext.json b/adapters/rtbhouse/rtbhousetest/supplemental/malformed-imp-ext.json new file mode 100644 index 00000000000..655f71899ea --- /dev/null +++ b/adapters/rtbhouse/rtbhousetest/supplemental/malformed-imp-ext.json @@ -0,0 +1,25 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": "invalid-json" + } + ] + }, + "expectedMakeRequestsErrors": [ + { + "value": "Bidder extension not provided or can't be unmarshalled", + "comparison": "literal" + } + ] +} \ No newline at end of file