From cfbbdeae1ec526898c4f3593421118f597ce2d00 Mon Sep 17 00:00:00 2001 From: Emil Nadimanov Date: Wed, 15 Jan 2025 15:22:11 +0100 Subject: [PATCH 1/2] Fix #3608 Smartadserver config: added audio support, endpoint compressions, alias --- src/main/resources/bidder-config/smartadserver.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/bidder-config/smartadserver.yaml b/src/main/resources/bidder-config/smartadserver.yaml index a4ff6fff510..3e1e75bc5d5 100644 --- a/src/main/resources/bidder-config/smartadserver.yaml +++ b/src/main/resources/bidder-config/smartadserver.yaml @@ -1,16 +1,21 @@ adapters: smartadserver: endpoint: https://ssb-global.smartadserver.com + endpoint-compression: gzip + aliases: + equativ: ~ meta-info: maintainer-email: supply-partner-integration@equativ.com app-media-types: - banner - video - native + - audio site-media-types: - banner - video - native + - audio supported-vendors: vendor-id: 45 usersync: From 1c1cc32a550c2aa072014fe5b76203ed38ea922b Mon Sep 17 00:00:00 2001 From: Emil Nadimanov Date: Wed, 15 Jan 2025 15:26:51 +0100 Subject: [PATCH 2/2] Fix #3608 Smartadserver: parse BidType from mType in the bid response --- .../smartadserver/SmartadserverBidder.java | 24 +++--- .../SmartadserverBidderTest.java | 81 ++++++++++++------- .../test-auction-smartadserver-response.json | 3 +- .../test-smartadserver-bid-response.json | 3 +- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java index 2622aae49cf..a9ee72df740 100644 --- a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java +++ b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java @@ -112,13 +112,13 @@ private static Publisher modifyPublisher(Publisher publisher, Integer networkId) public Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { try { final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); - return extractBids(httpCall.getRequest().getPayload(), bidResponse); + return extractBids(bidResponse); } catch (DecodeException | PreBidException e) { return Result.withError(BidderError.badServerResponse(e.getMessage())); } } - private Result> extractBids(BidRequest bidRequest, BidResponse bidResponse) { + private Result> extractBids(BidResponse bidResponse) { if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { return Result.empty(); } @@ -128,19 +128,21 @@ private Result> extractBids(BidRequest bidRequest, BidResponse b .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidTypeFromMarkupType(bid.getMtype()), bidResponse.getCur())) .toList(); return Result.of(bidderBids, errors); } - private static BidType getBidType(String impId, List imps) { - for (Imp imp : imps) { - if (imp.getId().equals(impId)) { - return imp.getVideo() != null - ? BidType.video - : (imp.getXNative() != null ? BidType.xNative : BidType.banner); - } + private static BidType getBidTypeFromMarkupType(Integer markupType) { + if (markupType == null) { + return BidType.banner; } - return BidType.banner; + return switch (markupType) { + case 1 -> BidType.banner; + case 2 -> BidType.video; + case 3 -> BidType.audio; + case 4 -> BidType.xNative; + default -> BidType.banner; + }; } } 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 35b7470f758..d31213136fb 100644 --- a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java @@ -4,7 +4,6 @@ import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Native; import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Video; @@ -27,8 +26,10 @@ import java.util.function.Function; import static java.util.Collections.singletonList; +import static java.util.function.UnaryOperator.identity; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.prebid.server.proto.openrtb.ext.response.BidType.audio; import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; import static org.prebid.server.proto.openrtb.ext.response.BidType.video; import static org.prebid.server.proto.openrtb.ext.response.BidType.xNative; @@ -66,7 +67,7 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { public void makeHttpRequestsShouldCreateCorrectURL() { // given final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(Function.identity()))) + .imp(singletonList(givenImp(identity()))) .build(); // when @@ -83,7 +84,7 @@ public void makeHttpRequestsShouldCreateCorrectURL() { public void makeHttpRequestsShouldUpdateSiteObjectIfPresent() { // given final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(Function.identity()))) + .imp(singletonList(givenImp(identity()))) .site(Site.builder() .domain("www.foo.com") .publisher(Publisher.builder().domain("foo.com").build()) @@ -110,7 +111,7 @@ public void makeHttpRequestsShouldUpdateSiteObjectIfPresent() { public void makeHttpRequestsShouldCreateRequestForEveryValidImp() { // given final BidRequest bidRequest = BidRequest.builder() - .imp(Arrays.asList(givenImp(Function.identity()), + .imp(Arrays.asList(givenImp(identity()), givenImp(impBuilder -> impBuilder.id("456")) )) .build(); @@ -196,14 +197,12 @@ public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws Jso } @Test - public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + public void makeBidsShouldReturnBannerBidIfMarkupTypeIsBanner() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build())) - .build(), + BidRequest.builder().build(), mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + givenBidResponse(bidBuilder -> bidBuilder.mtype(1)))); // when final Result> result = target.makeBids(httpCall, null); @@ -211,18 +210,33 @@ public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessi // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), banner, "EUR")); + .containsOnly(BidderBid.of(Bid.builder().mtype(1).build(), banner, "EUR")); } @Test - public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingException { + public void makeBidsShouldReturnAudioBidIfMarkupTypeIsAudio() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build())) - .build(), + BidRequest.builder().build(), mapper.writeValueAsString( - givenBidResponse(Function.identity()))); + givenBidResponse(bidBuilder -> bidBuilder.mtype(3)))); + + // when + final Result> result = target.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsOnly(BidderBid.of(Bid.builder().mtype(3).build(), audio, "EUR")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfMarkupTypeIsNull() throws JsonProcessingException { + // given + final BidderCall httpCall = givenHttpCall( + BidRequest.builder().build(), + mapper.writeValueAsString( + givenBidResponse(identity()))); // when final Result> result = target.makeBids(httpCall, null); @@ -234,14 +248,29 @@ public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingExcept } @Test - public void makeBidsShouldReturnVideoBidIfVideoIsPresent() throws JsonProcessingException { + public void makeBidsShouldReturnBannerBidIfMarkupTypeOutOfBounds() throws JsonProcessingException { + // given + final BidderCall httpCall = givenHttpCall( + BidRequest.builder().build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.mtype(5)))); + + // when + final Result> result = target.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsOnly(BidderBid.of(Bid.builder().mtype(5).build(), banner, "EUR")); + } + + @Test + public void makeBidsShouldReturnVideoBidIfMarkupTypeIsVideo() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").video(Video.builder().build()).build())) - .build(), + BidRequest.builder().build(), mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + givenBidResponse(bidBuilder -> bidBuilder.mtype(2)))); // when final Result> result = target.makeBids(httpCall, null); @@ -249,18 +278,16 @@ public void makeBidsShouldReturnVideoBidIfVideoIsPresent() throws JsonProcessing // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, "EUR")); + .containsOnly(BidderBid.of(Bid.builder().mtype(2).build(), video, "EUR")); } @Test - public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessingException { + public void makeBidsShouldReturnNativeBidIfMarkupTypeIsNative() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) - .build(), + BidRequest.builder().build(), mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + givenBidResponse(bidBuilder -> bidBuilder.mtype(4)))); // when final Result> result = target.makeBids(httpCall, null); @@ -268,7 +295,7 @@ public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessi // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "EUR")); + .containsOnly(BidderBid.of(Bid.builder().mtype(4).build(), xNative, "EUR")); } private static Imp givenImp(Function impCustomizer) { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json index 7b143f69a40..a4cd96d82b2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json @@ -22,7 +22,8 @@ "type": "banner" }, "origbidcpm": 0.5 - } + }, + "mtype": 1 } ], "seat": "smartadserver", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response.json index cee26a03931..09d1cc62eb9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response.json @@ -15,7 +15,8 @@ "cid": "cid", "crid": "crid", "h": 576, - "w": 1024 + "w": 1024, + "mtype": 1 } ] }