Skip to content

Commit 7b17943

Browse files
RodionOretsnickluck8
authored and
nickluck8
committed
IX: Set bidVideo when category and duration is available (#1274)
1 parent 3f22ea5 commit 7b17943

File tree

3 files changed

+86
-17
lines changed

3 files changed

+86
-17
lines changed

src/main/java/org/prebid/server/bidder/ix/IxBidder.java

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.prebid.server.bidder.ix;
22

3+
import com.fasterxml.jackson.core.JsonProcessingException;
34
import com.fasterxml.jackson.core.type.TypeReference;
5+
import com.fasterxml.jackson.databind.node.ObjectNode;
46
import com.iab.openrtb.request.Banner;
57
import com.iab.openrtb.request.BidRequest;
68
import com.iab.openrtb.request.Format;
@@ -24,6 +26,8 @@
2426
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
2527
import org.prebid.server.proto.openrtb.ext.request.ix.ExtImpIx;
2628
import org.prebid.server.proto.openrtb.ext.response.BidType;
29+
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
30+
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo;
2731
import org.prebid.server.util.HttpUtil;
2832

2933
import java.util.ArrayList;
@@ -194,21 +198,52 @@ public Result<List<BidderBid>> makeBids(HttpCall<BidRequest> httpCall, BidReques
194198
}
195199
}
196200

197-
private static List<BidderBid> extractBids(BidResponse bidResponse, BidRequest bidRequest) {
201+
private List<BidderBid> extractBids(BidResponse bidResponse, BidRequest bidRequest) {
198202
return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())
199203
? Collections.emptyList()
200204
: bidsFromResponse(bidResponse, bidRequest);
201205
}
202206

203-
private static List<BidderBid> bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) {
207+
private List<BidderBid> bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) {
204208
return bidResponse.getSeatbid().stream()
209+
.filter(Objects::nonNull)
205210
.map(SeatBid::getBid)
211+
.filter(Objects::nonNull)
206212
.flatMap(Collection::stream)
207-
.map(bid -> prepareBid(bid, bidRequest))
208-
.map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur()))
213+
.map(bid -> toBidderBid(bid, bidRequest, bidResponse))
209214
.collect(Collectors.toList());
210215
}
211216

217+
private BidderBid toBidderBid(Bid bid, BidRequest bidRequest, BidResponse bidResponse) {
218+
final BidType bidType = getBidType(bid.getImpid(), bidRequest.getImp());
219+
final ObjectNode bidExt = bid.getExt();
220+
final ExtBidPrebid extPrebid = bidExt != null ? parseBidExt(bidExt) : null;
221+
final ExtBidPrebidVideo extVideo = extPrebid != null ? extPrebid.getVideo() : null;
222+
final boolean bidHasNoSizes = bid.getH() == null || bid.getW() == null;
223+
final Banner banner = bidRequest.getImp().get(0).getBanner();
224+
225+
if ((bidHasNoSizes && banner != null) || (extVideo != null)) {
226+
final Bid.BidBuilder bidBuilder = bid.toBuilder();
227+
228+
if (bidType == BidType.banner && bidHasNoSizes && banner != null) {
229+
bidBuilder
230+
.w(banner.getW())
231+
.h(banner.getH())
232+
.build();
233+
}
234+
235+
if (bidType == BidType.video && extVideo != null) {
236+
bidBuilder.ext(resolveBidExt(extVideo.getDuration()));
237+
if (CollectionUtils.isEmpty(bid.getCat())) {
238+
bidBuilder.cat(Collections.singletonList(extVideo.getPrimaryCategory())).build();
239+
}
240+
}
241+
bid = bidBuilder.build();
242+
}
243+
244+
return BidderBid.of(bid, bidType, bidResponse.getCur());
245+
}
246+
212247
private static BidType getBidType(String impId, List<Imp> imps) {
213248
for (Imp imp : imps) {
214249
if (imp.getId().equals(impId)) {
@@ -226,16 +261,17 @@ private static BidType getBidType(String impId, List<Imp> imps) {
226261
throw new PreBidException(String.format("Unmatched impression id %s", impId));
227262
}
228263

229-
private static Bid prepareBid(Bid bid, BidRequest bidRequest) {
230-
// Current implementation ensure that we have at least one imp in request
231-
final boolean bidHasNoSizes = bid.getH() == null || bid.getW() == null;
232-
final Banner banner = bidRequest.getImp().get(0).getBanner();
233-
if (bidHasNoSizes && banner != null) {
234-
return bid.toBuilder()
235-
.w(banner.getW())
236-
.h(banner.getH())
237-
.build();
264+
private ExtBidPrebid parseBidExt(ObjectNode bidExt) {
265+
try {
266+
return mapper.mapper().treeToValue(bidExt, ExtBidPrebid.class);
267+
} catch (JsonProcessingException e) {
268+
throw new PreBidException(e.getMessage());
238269
}
239-
return bid;
270+
}
271+
272+
private ObjectNode resolveBidExt(Integer duration) {
273+
return mapper.mapper().valueToTree(ExtBidPrebid.builder()
274+
.video(ExtBidPrebidVideo.of(duration, null))
275+
.build());
240276
}
241277
}

src/main/resources/bidder-config/ix.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
adapters:
22
ix:
33
enabled: false
4-
endpoint: http://rubicon-us-east.lb.indexww.com/transbidder?p=189517
4+
endpoint: https://
55
pbs-enforces-gdpr: true
66
pbs-enforces-ccpa: true
77
modifying-vast-xml-allowed: true
@@ -22,8 +22,8 @@ adapters:
2222
supported-vendors:
2323
vendor-id: 10
2424
usersync:
25-
url:
26-
redirect-url:
25+
url: https://ssum.casalemedia.com/usermatchredir?s=189517&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb=
26+
redirect-url: /setuid?bidder=ix&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&uid=
2727
cookie-family-name: ix
2828
type: redirect
2929
support-cors: false

src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
2424
import org.prebid.server.proto.openrtb.ext.request.ix.ExtImpIx;
2525
import org.prebid.server.proto.openrtb.ext.response.BidType;
26+
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
27+
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo;
2628

2729
import java.util.ArrayList;
2830
import java.util.List;
@@ -33,6 +35,7 @@
3335
import static java.util.function.Function.identity;
3436
import static org.assertj.core.api.Assertions.assertThat;
3537
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
38+
import static org.assertj.core.api.Assertions.tuple;
3639

3740
public class IxBidderTest extends VertxTest {
3841

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

380+
@Test
381+
public void makeBidsShouldReturnBidWithVideoExt() throws JsonProcessingException {
382+
// given
383+
final Video video = Video.builder().build();
384+
final HttpCall<BidRequest> httpCall = givenHttpCall(
385+
BidRequest.builder()
386+
.imp(singletonList(Imp.builder().id("123").video(video).build()))
387+
.build(),
388+
mapper.writeValueAsString(
389+
givenBidResponse(
390+
bidBuilder -> bidBuilder
391+
.impid("123")
392+
.ext(mapper.valueToTree(ExtBidPrebid.builder()
393+
.video(ExtBidPrebidVideo.of(1, "cat"))
394+
.build())))));
395+
396+
// when
397+
final Result<List<BidderBid>> result = ixBidder.makeBids(httpCall, null);
398+
399+
// then
400+
assertThat(result.getErrors()).isEmpty();
401+
assertThat(result.getValue())
402+
.extracting(BidderBid::getBid)
403+
.extracting(Bid::getExt)
404+
.extracting(node -> mapper.treeToValue(node, ExtBidPrebid.class))
405+
.extracting(ExtBidPrebid::getVideo)
406+
.extracting(ExtBidPrebidVideo::getDuration, ExtBidPrebidVideo::getPrimaryCategory)
407+
.containsExactly(tuple(1, null));
408+
}
409+
377410
private static BidRequest givenBidRequest(
378411
Function<BidRequest.BidRequestBuilder, BidRequest.BidRequestBuilder> bidRequestCustomizer,
379412
Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer) {

0 commit comments

Comments
 (0)