diff --git a/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java b/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java index 27bf22aef2a..db9194ee215 100644 --- a/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java +++ b/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java @@ -18,6 +18,7 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; @@ -90,7 +91,7 @@ private static BidType getBidType(Bid bid) { private ObjectNode makeExt(String networkName) { return mapper.mapper().valueToTree(ExtBidPrebid.builder() - .meta(mapper.mapper().createObjectNode().put("networkName", networkName)) + .meta(ExtBidPrebidMeta.builder().networkName(networkName).build()) .build()); } } diff --git a/src/main/java/org/prebid/server/bidder/grid/GridBidder.java b/src/main/java/org/prebid/server/bidder/grid/GridBidder.java index 981a7682a5d..8ecabeff5ab 100644 --- a/src/main/java/org/prebid/server/bidder/grid/GridBidder.java +++ b/src/main/java/org/prebid/server/bidder/grid/GridBidder.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.MissingNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Site; @@ -34,6 +33,7 @@ import org.prebid.server.proto.openrtb.ext.request.grid.ExtImpGrid; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; @@ -235,7 +235,7 @@ private ObjectNode modifyBidExt(ObjectNode gridBid) { } final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder() - .meta(mapper.mapper().createObjectNode().set("demandsource", TextNode.valueOf(demandSource))) + .meta(ExtBidPrebidMeta.builder().demandSource(demandSource).build()) .build(); return mapper.mapper().valueToTree(ExtPrebid.of(extBidPrebid, null)); } diff --git a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java index b3c9293bc5e..7943b3b04b2 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import com.iab.openrtb.request.App; @@ -105,6 +104,7 @@ import org.prebid.server.proto.openrtb.ext.request.rubicon.RubiconVideoParams; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; @@ -1640,10 +1640,10 @@ private RubiconBid insertNetworkIdToMeta(RubiconBid bid, int networkId, List renderers; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdkRenderer.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdkRenderer.java new file mode 100644 index 00000000000..0ad4f0a0779 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdkRenderer.java @@ -0,0 +1,32 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Value; + +/** + * Defines the contract for bidrequest.ext.prebid.sdk.renderers[i] + */ +@Value(staticConstructor = "of") +public class ExtRequestPrebidSdkRenderer { + + /** + * Defines the contract for bidrequest.ext.prebid.sdk.renderers[i].name + */ + String name; + + /** + * Defines the contract for bidrequest.ext.prebid.sdk.renderers[i].version + */ + String version; + + /** + * Defines the contract for bidrequest.ext.prebid.sdk.renderers[i].url + */ + String url; + + /** + * Defines the contract for bidrequest.ext.prebid.sdk.renderers[i].data + */ + ObjectNode data; + +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java index bef79852ab7..d116447caed 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Video; import lombok.Builder; import lombok.Value; @@ -34,7 +33,7 @@ public class ExtBidPrebid { ExtBidPrebidVideo video; - ObjectNode meta; + ExtBidPrebidMeta meta; @JsonProperty("dealtiersatisfied") Boolean dealTierSatisfied; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebidMeta.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebidMeta.java new file mode 100644 index 00000000000..b7295616a82 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebidMeta.java @@ -0,0 +1,70 @@ +package org.prebid.server.proto.openrtb.ext.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +@Builder(toBuilder = true) +@Value +public class ExtBidPrebidMeta { + + @JsonProperty("adaptercode") + String adapterCode; + + @JsonProperty("advertiserDomains") + List advertiserDomains; + + @JsonProperty("advertiserId") + Integer advertiserId; + + @JsonProperty("advertiserName") + String advertiserName; + + @JsonProperty("agencyId") + Integer agencyId; + + @JsonProperty("agencyName") + String agencyName; + + @JsonProperty("brandId") + Integer brandId; + + @JsonProperty("brandName") + String brandName; + + ObjectNode dchain; + + @JsonProperty("demandSource") + String demandSource; + + @JsonProperty("mediaType") + String mediaType; + + @JsonProperty("networkId") + Integer networkId; + + @JsonProperty("networkName") + String networkName; + + @JsonProperty("primaryCatId") + String primaryCategoryId; + + @JsonProperty("rendererName") + String rendererName; + + @JsonProperty("rendererVersion") + String rendererVersion; + + @JsonProperty("rendererUrl") + String rendererUrl; + + @JsonProperty("rendererData") + ObjectNode rendererData; + + @JsonProperty("secondaryCatIds") + List secondaryCategoryIdList; + +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy index 21a68bcc15d..3cbbbe9ed7b 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy @@ -34,6 +34,7 @@ class Prebid { Map passThrough Events events Boolean createTids + Sdk sdk static class Channel { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Renderer.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Renderer.groovy new file mode 100644 index 00000000000..c4fcf737f6f --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Renderer.groovy @@ -0,0 +1,12 @@ +package org.prebid.server.functional.model.request.auction + +import groovy.transform.ToString + +@ToString(includeNames = true, ignoreNulls = true) +class Renderer { + + String name + String version + String url + RendererData data +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/RendererData.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/RendererData.groovy new file mode 100644 index 00000000000..50d0bb9508c --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/RendererData.groovy @@ -0,0 +1,9 @@ +package org.prebid.server.functional.model.request.auction + +import groovy.transform.ToString + +@ToString(includeNames = true, ignoreNulls = true) +class RendererData { + + String any +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Sdk.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Sdk.groovy new file mode 100644 index 00000000000..3dfe84952e0 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Sdk.groovy @@ -0,0 +1,9 @@ +package org.prebid.server.functional.model.request.auction + +import groovy.transform.ToString + +@ToString(includeNames = true, ignoreNulls = true) +class Sdk { + + List renderers +} diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy new file mode 100644 index 00000000000..d022daf9646 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy @@ -0,0 +1,27 @@ +package org.prebid.server.functional.model.response.auction + +import groovy.transform.ToString +import org.prebid.server.functional.model.request.auction.RendererData + +@ToString(includeNames = true, ignoreNulls = true) +class Meta { + + String adapterCode + List advertiserDomains + Integer advertiserId + String advertiserName + Integer agencyId + String agencyName + Integer brandId + String brandName + String demandSource + String mediaType + Integer networkId + String networkName + String primaryCategoryId + String rendererName + String rendererVersion + String rendererUrl + RendererData rendererData + List secondaryCategoryIdList +} diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy index 34ce917e1c6..e894510811c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy @@ -11,5 +11,6 @@ class Prebid { String targetBidderCode Cache cache Events events + Meta meta Map passThrough } diff --git a/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy index 5cd4a597490..0f28f95ecdd 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy @@ -4,9 +4,16 @@ import org.prebid.server.functional.model.UidsCookie import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.PrebidStoredRequest +import org.prebid.server.functional.model.request.auction.Renderer +import org.prebid.server.functional.model.request.auction.RendererData +import org.prebid.server.functional.model.request.auction.Sdk import org.prebid.server.functional.model.request.auction.User import org.prebid.server.functional.model.request.auction.UserExt import org.prebid.server.functional.model.request.auction.UserExtPrebid +import org.prebid.server.functional.model.response.auction.BidExt +import org.prebid.server.functional.model.response.auction.BidResponse +import org.prebid.server.functional.model.response.auction.Meta +import org.prebid.server.functional.model.response.auction.Prebid import org.prebid.server.functional.model.response.cookiesync.UserSyncInfo import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService @@ -310,4 +317,50 @@ class AuctionSpec extends BaseSpec { and: "BidderRequest shouldn't populate fields" assert !bidderRequest.ext.prebid.aliases } + + def "PBS auction should pass ext.prebid.sdk requested to bidder request when sdk specified"() { + given: "Default bid request with aliases" + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.sdk = new Sdk(renderers: [new Renderer( + name: PBSUtils.randomString, + version: PBSUtils.randomString, + data: new RendererData(any: PBSUtils.randomString))]) + } + + when: "Requesting PBS auction" + defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Bidder request should contain sdk value same in request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.ext.prebid.sdk.renderers.name == bidRequest.ext.prebid.sdk.renderers.name + assert bidderRequest.ext.prebid.sdk.renderers.version == bidRequest.ext.prebid.sdk.renderers.version + assert bidderRequest.ext.prebid.sdk.renderers.data.any == bidRequest.ext.prebid.sdk.renderers.data.any + } + + def "PBS auction should pass meta object to bid response when meta specified "() { + given: "Default bid request with aliases" + def bidRequest = BidRequest.defaultBidRequest + + and: "Default bidder response without bid" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + seatbid[0].bid[0].ext = new BidExt(prebid: new Prebid(meta: new Meta( + rendererName: PBSUtils.randomString, + rendererUrl: PBSUtils.randomString, + rendererVersion: PBSUtils.getRandomString()))) + } + + and: "Set bidder response" + bidder.setResponse(bidRequest.id, bidResponse) + + when: "Requesting PBS auction" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Bid response should contain meta value same in request" + assert response.seatbid[0].bid[0].ext.prebid.meta.rendererName == + bidResponse.seatbid[0].bid[0].ext.prebid.meta.rendererName + assert response.seatbid[0].bid[0].ext.prebid.meta.rendererUrl == + bidResponse.seatbid[0].bid[0].ext.prebid.meta.rendererUrl + assert response.seatbid[0].bid[0].ext.prebid.meta.rendererVersion == + bidResponse.seatbid[0].bid[0].ext.prebid.meta.rendererVersion + } } diff --git a/src/test/java/org/prebid/server/bidder/grid/GridBidderTest.java b/src/test/java/org/prebid/server/bidder/grid/GridBidderTest.java index 2444c3bf830..428fc472cbe 100644 --- a/src/test/java/org/prebid/server/bidder/grid/GridBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/grid/GridBidderTest.java @@ -30,6 +30,7 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.grid.ExtImpGrid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import java.io.IOException; import java.util.List; @@ -370,8 +371,7 @@ public void makeBidsShouldModifyBidExtWithMetaIfDemandSourceIsPresentInBidExt() // then assertThat(result.getErrors()).isEmpty(); - final ObjectNode expectedBidMeta = mapper.createObjectNode() - .set("demandsource", TextNode.valueOf("demandSource")); + final ExtBidPrebidMeta expectedBidMeta = ExtBidPrebidMeta.builder().demandSource("demandSource").build(); final ObjectNode expectedBidExt = mapper.valueToTree( ExtPrebid.of(ExtBidPrebid.builder().meta(expectedBidMeta).build(), null)); diff --git a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java index 8dcf3834c1e..e917ef85572 100644 --- a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java @@ -105,6 +105,7 @@ import org.prebid.server.proto.openrtb.ext.request.rubicon.ExtImpRubiconDebug; import org.prebid.server.proto.openrtb.ext.request.rubicon.RubiconVideoParams; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.util.HttpUtil; import java.io.IOException; @@ -3269,7 +3270,7 @@ public void makeBidsShouldSetSeatBuyerToMetaNetworkId() throws JsonProcessingExc // then final ObjectNode expectedBidExt = mapper.valueToTree( ExtPrebid.of(ExtBidPrebid.builder() - .meta(mapper.createObjectNode().set("networkId", IntNode.valueOf(123))) + .meta(ExtBidPrebidMeta.builder().networkId(123).build()) .build(), null)); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) @@ -3702,7 +3703,9 @@ public void makeBidsShouldReturnBidWithCurrencyFromBidResponse() throws JsonProc public void makeBidsShouldReturnBidWithDchainFromRequest() throws JsonProcessingException { // given final ObjectNode requestNode = mapper.valueToTree(ExtBidPrebid.builder() - .meta(mapper.createObjectNode().set("dChain", TextNode.valueOf("dChain"))) + .meta(ExtBidPrebidMeta.builder() + .dchain(mapper.createObjectNode().set("dChain", TextNode.valueOf("dChain"))) + .build()) .build()); final BidderCall httpCall = givenHttpCall( givenBidRequest(identity()), diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-request.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-request.json index 0055b4859ec..a385a8a1275 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-request.json @@ -25,6 +25,22 @@ }, "ext": { "prebid": { + "sdk": { + "renderers": [ + { + "name":"PrebidRenderer", + "version":"2.1.1", + "data": { + "someData": "someData" + } + }, + { + "name":"SampleRenderer", + "version":"1.0.0", + "url": "rendererUrl" + } + ] + }, "bidadjustmentfactors": { "mediatypes": { "video": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json index d78e40c1099..7860b71387c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json @@ -35,6 +35,14 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } + }, + "meta": { + "rendererName": "SamplePluginRenderer", + "rendererVersion": "1.0.0", + "rendererData": { + "data": "some data" + }, + "rendererUrl": "rendererUrl" } }, "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json index 396c885a724..5cae795f22a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json @@ -14,7 +14,15 @@ "h": 250, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "rendererName": "SamplePluginRenderer", + "rendererVersion": "1.0.0", + "rendererData": { + "data": "some data" + }, + "rendererUrl": "rendererUrl" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-request.json index 55bc5028b49..4c75cbcfa5c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-request.json @@ -71,6 +71,22 @@ "gvlid" : 1, "datacenter" : "local", "endpoint" : "/openrtb2/auction" + }, + "sdk": { + "renderers": [ + { + "name":"PrebidRenderer", + "version":"2.1.1", + "data": { + "someData": "someData" + } + }, + { + "name":"SampleRenderer", + "version":"1.0.0", + "url": "rendererUrl" + } + ] } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-response.json index 95a93284e04..cd18ad69edc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-generic-bid-response.json @@ -12,9 +12,21 @@ "cid": "cid001", "adm": "adm001", "h": 250, - "w": 300 + "w": 300, + "ext": { + "prebid": { + "meta": { + "rendererName": "SamplePluginRenderer", + "rendererVersion": "1.0.0", + "rendererData": { + "data": "some data" + }, + "rendererUrl": "rendererUrl" + } + } + } } ] } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json index 6e8dfa6ac51..a71711d597d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json @@ -17,7 +17,7 @@ "prebid": { "type": "banner", "meta": { - "demandsource": "trustx" + "demandSource": "trustx" } }, "origbidcpm": 3.33