Skip to content

Commit

Permalink
IX: Set bidVideo when category and duration is available (#1274)
Browse files Browse the repository at this point in the history
  • Loading branch information
RodionOrets authored and nickluck8 committed Aug 10, 2021
1 parent 3f22ea5 commit 7b17943
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 17 deletions.
64 changes: 50 additions & 14 deletions src/main/java/org/prebid/server/bidder/ix/IxBidder.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.prebid.server.bidder.ix;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iab.openrtb.request.Banner;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Format;
Expand All @@ -24,6 +26,8 @@
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
import org.prebid.server.proto.openrtb.ext.request.ix.ExtImpIx;
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.ExtBidPrebidVideo;
import org.prebid.server.util.HttpUtil;

import java.util.ArrayList;
Expand Down Expand Up @@ -194,21 +198,52 @@ public Result<List<BidderBid>> makeBids(HttpCall<BidRequest> httpCall, BidReques
}
}

private static List<BidderBid> extractBids(BidResponse bidResponse, BidRequest bidRequest) {
private List<BidderBid> extractBids(BidResponse bidResponse, BidRequest bidRequest) {
return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())
? Collections.emptyList()
: bidsFromResponse(bidResponse, bidRequest);
}

private static List<BidderBid> bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) {
private List<BidderBid> bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) {
return bidResponse.getSeatbid().stream()
.filter(Objects::nonNull)
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(bid -> prepareBid(bid, bidRequest))
.map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur()))
.map(bid -> toBidderBid(bid, bidRequest, bidResponse))
.collect(Collectors.toList());
}

private BidderBid toBidderBid(Bid bid, BidRequest bidRequest, BidResponse bidResponse) {
final BidType bidType = getBidType(bid.getImpid(), bidRequest.getImp());
final ObjectNode bidExt = bid.getExt();
final ExtBidPrebid extPrebid = bidExt != null ? parseBidExt(bidExt) : null;
final ExtBidPrebidVideo extVideo = extPrebid != null ? extPrebid.getVideo() : null;
final boolean bidHasNoSizes = bid.getH() == null || bid.getW() == null;
final Banner banner = bidRequest.getImp().get(0).getBanner();

if ((bidHasNoSizes && banner != null) || (extVideo != null)) {
final Bid.BidBuilder bidBuilder = bid.toBuilder();

if (bidType == BidType.banner && bidHasNoSizes && banner != null) {
bidBuilder
.w(banner.getW())
.h(banner.getH())
.build();
}

if (bidType == BidType.video && extVideo != null) {
bidBuilder.ext(resolveBidExt(extVideo.getDuration()));
if (CollectionUtils.isEmpty(bid.getCat())) {
bidBuilder.cat(Collections.singletonList(extVideo.getPrimaryCategory())).build();
}
}
bid = bidBuilder.build();
}

return BidderBid.of(bid, bidType, bidResponse.getCur());
}

private static BidType getBidType(String impId, List<Imp> imps) {
for (Imp imp : imps) {
if (imp.getId().equals(impId)) {
Expand All @@ -226,16 +261,17 @@ private static BidType getBidType(String impId, List<Imp> imps) {
throw new PreBidException(String.format("Unmatched impression id %s", impId));
}

private static Bid prepareBid(Bid bid, BidRequest bidRequest) {
// Current implementation ensure that we have at least one imp in request
final boolean bidHasNoSizes = bid.getH() == null || bid.getW() == null;
final Banner banner = bidRequest.getImp().get(0).getBanner();
if (bidHasNoSizes && banner != null) {
return bid.toBuilder()
.w(banner.getW())
.h(banner.getH())
.build();
private ExtBidPrebid parseBidExt(ObjectNode bidExt) {
try {
return mapper.mapper().treeToValue(bidExt, ExtBidPrebid.class);
} catch (JsonProcessingException e) {
throw new PreBidException(e.getMessage());
}
return bid;
}

private ObjectNode resolveBidExt(Integer duration) {
return mapper.mapper().valueToTree(ExtBidPrebid.builder()
.video(ExtBidPrebidVideo.of(duration, null))
.build());
}
}
6 changes: 3 additions & 3 deletions src/main/resources/bidder-config/ix.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
adapters:
ix:
enabled: false
endpoint: http://rubicon-us-east.lb.indexww.com/transbidder?p=189517
endpoint: https://
pbs-enforces-gdpr: true
pbs-enforces-ccpa: true
modifying-vast-xml-allowed: true
Expand All @@ -22,8 +22,8 @@ adapters:
supported-vendors:
vendor-id: 10
usersync:
url:
redirect-url:
url: https://ssum.casalemedia.com/usermatchredir?s=189517&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb=
redirect-url: /setuid?bidder=ix&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&uid=
cookie-family-name: ix
type: redirect
support-cors: false
33 changes: 33 additions & 0 deletions src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
import org.prebid.server.proto.openrtb.ext.request.ix.ExtImpIx;
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.ExtBidPrebidVideo;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -33,6 +35,7 @@
import static java.util.function.Function.identity;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.tuple;

public class IxBidderTest extends VertxTest {

Expand Down Expand Up @@ -374,6 +377,36 @@ public void makeBidsShouldReturnBannerBidWithRequestImpSizeWhenBidSizeIsEmpty()
.containsOnly(BidderBid.of(Bid.builder().impid("123").w(300).h(200).build(), BidType.banner, "EUR"));
}

@Test
public void makeBidsShouldReturnBidWithVideoExt() throws JsonProcessingException {
// given
final Video video = Video.builder().build();
final HttpCall<BidRequest> httpCall = givenHttpCall(
BidRequest.builder()
.imp(singletonList(Imp.builder().id("123").video(video).build()))
.build(),
mapper.writeValueAsString(
givenBidResponse(
bidBuilder -> bidBuilder
.impid("123")
.ext(mapper.valueToTree(ExtBidPrebid.builder()
.video(ExtBidPrebidVideo.of(1, "cat"))
.build())))));

// when
final Result<List<BidderBid>> result = ixBidder.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.extracting(BidderBid::getBid)
.extracting(Bid::getExt)
.extracting(node -> mapper.treeToValue(node, ExtBidPrebid.class))
.extracting(ExtBidPrebid::getVideo)
.extracting(ExtBidPrebidVideo::getDuration, ExtBidPrebidVideo::getPrimaryCategory)
.containsExactly(tuple(1, null));
}

private static BidRequest givenBidRequest(
Function<BidRequest.BidRequestBuilder, BidRequest.BidRequestBuilder> bidRequestCustomizer,
Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer) {
Expand Down

0 comments on commit 7b17943

Please sign in to comment.