diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java index efc8de91a5f..fddb476993b 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java @@ -1,5 +1,6 @@ package org.prebid.server.proto.openrtb.ext.request.smartadserver; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Value; @@ -20,4 +21,13 @@ public class ExtImpSmartadserver { @JsonProperty(value = "programmaticGuaranteed", access = JsonProperty.Access.WRITE_ONLY) boolean programmaticGuaranteed; + + @JsonProperty(value = "placementuuid", access = JsonProperty.Access.WRITE_ONLY) + String placementUuid; + + @JsonProperty(value = "plcmtuuid", access = JsonProperty.Access.READ_ONLY) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public String getPlcmtuuid() { + return placementUuid; + } } diff --git a/src/main/resources/static/bidder-params/smartadserver.json b/src/main/resources/static/bidder-params/smartadserver.json index b9b28c7588b..42a0449bdcc 100644 --- a/src/main/resources/static/bidder-params/smartadserver.json +++ b/src/main/resources/static/bidder-params/smartadserver.json @@ -23,6 +23,10 @@ "type": "integer", "description": "The network id.", "minimum": 1 + }, + "placementuuid": { + "type": "string", + "description": "The placement UUID (new inventory structure). Preferred over siteId/pageId/formatId; forwarded to Equativ as plcmtuuid." } }, "dependencies": { diff --git a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java index c91a8e28ea1..45807450a3b 100644 --- a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java @@ -39,6 +39,7 @@ public class SmartadserverBidderTest extends VertxTest { private static final String ENDPOINT_URL = "https://test.endpoint.com/path/api/bid?testParam=testVal"; private static final String SECONDARY_URL = "https://test.endpoint2.com/path/ortb?testParam=testVal"; + private static final String PLACEMENT_UUID = "0ac7b8e4-8f35-4d1b-9a3c-2b7c0f7d9e11"; private final SmartadserverBidder target = new SmartadserverBidder(ENDPOINT_URL, SECONDARY_URL, jacksonMapper); @@ -217,7 +218,8 @@ public void makeHttpRequestsShouldModifyImpWhenProgrammaticGuaranteedIsTrueAtLea .put("networkId", 5) .put("siteId", 6) .put("formatId", 7) - .put("pageId", 8)); + .put("pageId", 8) + .put("placementuuid", PLACEMENT_UUID)); final BidRequest bidRequest = BidRequest.builder() .imp(List.of( @@ -240,7 +242,8 @@ public void makeHttpRequestsShouldModifyImpWhenProgrammaticGuaranteedIsTrueAtLea .put("networkId", 5) .put("siteId", 6) .put("formatId", 7) - .put("pageId", 8)); + .put("pageId", 8) + .put("plcmtuuid", PLACEMENT_UUID)); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).hasSize(1); @@ -251,6 +254,98 @@ public void makeHttpRequestsShouldModifyImpWhenProgrammaticGuaranteedIsTrueAtLea .containsExactly(expectedImpExt1, expectedImpExt2); } + @Test + public void makeHttpRequestsShouldForwardPlacementUuidAsPlcmtuuid() { + // given + final ObjectNode givenImpExt = mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .put("networkId", 73) + .put("placementuuid", PLACEMENT_UUID)); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(imp -> imp.ext(givenImpExt)))) + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedImpExt = mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .put("networkId", 73) + .put("plcmtuuid", PLACEMENT_UUID)); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedImpExt); + } + + @Test + public void makeHttpRequestsShouldForwardPlacementUuidAndLegacyIdsWhenBothPresent() { + // given + final ObjectNode givenImpExt = mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .put("siteId", 1) + .put("pageId", 2) + .put("formatId", 3) + .put("networkId", 73) + .put("placementuuid", PLACEMENT_UUID)); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(imp -> imp.ext(givenImpExt)))) + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedImpExt = mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .put("siteId", 1) + .put("pageId", 2) + .put("formatId", 3) + .put("networkId", 73) + .put("plcmtuuid", PLACEMENT_UUID)); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedImpExt); + } + + @Test + public void makeHttpRequestsShouldIgnoreInboundPlcmtuuid() { + // given + final ObjectNode givenImpExt = mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .put("networkId", 73) + .put("plcmtuuid", PLACEMENT_UUID)); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(imp -> imp.ext(givenImpExt)))) + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedImpExt = mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .put("networkId", 73)); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedImpExt); + } + @Test public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { // given @@ -403,7 +498,7 @@ private static Imp givenImp(Function impCustomiz .video(Video.builder().build()) .ext(mapper.valueToTree(ExtPrebid.of( null, - ExtImpSmartadserver.of(1, 2, 3, 4, false))))) + ExtImpSmartadserver.of(1, 2, 3, 4, false, null))))) .build(); } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json index b02d4d0a642..67e6448b192 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json @@ -15,6 +15,7 @@ "pageId": 2, "formatId": 3, "networkId": 73, + "placementuuid": "0ac7b8e4-8f35-4d1b-9a3c-2b7c0f7d9e11", "programmaticGuaranteed": true } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json index 3c429761287..0dae2002548 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json @@ -14,7 +14,8 @@ "siteId": 1, "pageId": 2, "formatId": 3, - "networkId": 73 + "networkId": 73, + "plcmtuuid": "0ac7b8e4-8f35-4d1b-9a3c-2b7c0f7d9e11" } } }