Skip to content

Commit c23a907

Browse files
committed
Pubmatic Adapter: Set bid.meta.mediaType=video when bid.ext.ibv=true
1 parent 9d07434 commit c23a907

5 files changed

Lines changed: 197 additions & 102 deletions

File tree

src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java

Lines changed: 76 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.prebid.server.proto.openrtb.ext.request.pubmatic.ExtImpPubmaticKeyVal;
4343
import org.prebid.server.proto.openrtb.ext.response.BidType;
4444
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
45+
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta;
4546
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo;
4647
import org.prebid.server.proto.openrtb.ext.response.ExtIgi;
4748
import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs;
@@ -504,6 +505,7 @@ public CompositeBidderResponse makeBidderResponse(BidderCall<BidRequest> httpCal
504505
return CompositeBidderResponse.builder()
505506
.bids(extractBids(bidResponse, errors))
506507
.igi(extractIgi(bidResponse))
508+
.errors(errors)
507509
.build();
508510
} catch (DecodeException | PreBidException e) {
509511
return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage()));
@@ -516,13 +518,67 @@ private List<BidderBid> extractBids(PubmaticBidResponse bidResponse, List<Bidder
516518
: bidsFromResponse(bidResponse, bidderErrors);
517519
}
518520

521+
private static BidType getBidType(Bid bid, List<BidderError> errors) {
522+
return switch (bid.getMtype()) {
523+
case 1 -> BidType.banner;
524+
case 2 -> BidType.video;
525+
case 3 -> BidType.audio;
526+
case 4 -> BidType.xNative;
527+
case null, default -> {
528+
errors.add(BidderError.badServerResponse("failed to parse bid mtype (%d) for impression id %s"
529+
.formatted(bid.getMtype(), bid.getImpid())));
530+
yield null;
531+
}
532+
};
533+
}
534+
535+
private static Integer getDuration(PubmaticBidExt bidExt) {
536+
return Optional.ofNullable(bidExt)
537+
.map(PubmaticBidExt::getVideo)
538+
.map(VideoCreativeInfo::getDuration)
539+
.orElse(null);
540+
}
541+
542+
private PubmaticBidExt parseBidExt(ObjectNode bidExt, List<BidderError> errors) {
543+
try {
544+
return bidExt != null ? mapper.mapper().treeToValue(bidExt, PubmaticBidExt.class) : null;
545+
} catch (JsonProcessingException e) {
546+
errors.add(BidderError.badServerResponse(e.getMessage()));
547+
return null;
548+
}
549+
}
550+
551+
private static boolean getInBannerVideo(PubmaticBidExt bidExt) {
552+
return Optional.ofNullable(bidExt)
553+
.map(PubmaticBidExt::getInBannerVideo)
554+
.orElse(false);
555+
}
556+
557+
private String resolveNativeAdm(String adm, List<BidderError> bidderErrors) {
558+
final JsonNode admNode;
559+
try {
560+
admNode = mapper.mapper().readTree(adm);
561+
} catch (JsonProcessingException e) {
562+
bidderErrors.add(BidderError.badServerResponse("Unable to parse native adm: %s".formatted(adm)));
563+
return null;
564+
}
565+
566+
final JsonNode nativeNode = admNode.get("native");
567+
if (nativeNode != null && !nativeNode.isMissingNode()) {
568+
return nativeNode.toString();
569+
}
570+
571+
return null;
572+
}
573+
519574
private List<BidderBid> bidsFromResponse(PubmaticBidResponse bidResponse, List<BidderError> bidderErrors) {
520575
return bidResponse.getSeatbid().stream()
521576
.filter(Objects::nonNull)
522577
.map(SeatBid::getBid)
523578
.filter(Objects::nonNull)
524579
.flatMap(Collection::stream)
525580
.map(bid -> resolveBidderBid(bid, bidResponse.getCur(), bidderErrors))
581+
.filter(Objects::nonNull)
526582
.toList();
527583
}
528584

@@ -533,21 +589,22 @@ private BidderBid resolveBidderBid(Bid bid, String currency, List<BidderError> b
533589
: null;
534590

535591
final PubmaticBidExt pubmaticBidExt = parseBidExt(bid.getExt(), bidderErrors);
536-
final Integer duration = getDuration(pubmaticBidExt);
537-
final BidType bidType = getBidType(pubmaticBidExt);
592+
final BidType bidType = getBidType(bid, bidderErrors);
593+
594+
if (bidType == null) {
595+
return null;
596+
}
538597

539598
final String bidAdm = bid.getAdm();
540599
final String resolvedAdm = bidAdm != null && bidType == BidType.xNative
541600
? resolveNativeAdm(bidAdm, bidderErrors)
542601
: bidAdm;
543602

544-
final Bid updatedBid = firstCat != null || duration != null || resolvedAdm != null
545-
? bid.toBuilder()
603+
final Bid updatedBid = bid.toBuilder()
546604
.cat(firstCat)
547605
.adm(resolvedAdm != null ? resolvedAdm : bidAdm)
548-
.ext(duration != null ? updateBidExtWithExtPrebid(duration, bid.getExt()) : bid.getExt())
549-
.build()
550-
: bid;
606+
.ext(updateBidExtWithExtPrebid(pubmaticBidExt, bidType, bid.getExt()))
607+
.build();
551608

552609
return BidderBid.builder()
553610
.bid(updatedBid)
@@ -558,54 +615,20 @@ private BidderBid resolveBidderBid(Bid bid, String currency, List<BidderError> b
558615
.build();
559616
}
560617

561-
private PubmaticBidExt parseBidExt(ObjectNode bidExt, List<BidderError> errors) {
562-
try {
563-
return bidExt != null ? mapper.mapper().treeToValue(bidExt, PubmaticBidExt.class) : null;
564-
} catch (JsonProcessingException e) {
565-
errors.add(BidderError.badServerResponse(e.getMessage()));
566-
return null;
567-
}
568-
}
569-
570-
private static Integer getDuration(PubmaticBidExt bidExt) {
571-
return Optional.ofNullable(bidExt)
572-
.map(PubmaticBidExt::getVideo)
573-
.map(VideoCreativeInfo::getDuration)
574-
.orElse(null);
575-
}
576-
577-
private static BidType getBidType(PubmaticBidExt bidExt) {
578-
final int bidType = Optional.ofNullable(bidExt)
579-
.map(PubmaticBidExt::getBidType)
580-
.orElse(0);
581-
582-
return switch (bidType) {
583-
case 1 -> BidType.video;
584-
case 2 -> BidType.xNative;
585-
default -> BidType.banner;
586-
};
587-
}
588-
589-
private String resolveNativeAdm(String adm, List<BidderError> bidderErrors) {
590-
final JsonNode admNode;
591-
try {
592-
admNode = mapper.mapper().readTree(adm);
593-
} catch (JsonProcessingException e) {
594-
bidderErrors.add(BidderError.badServerResponse("Unable to parse native adm: %s".formatted(adm)));
595-
return null;
596-
}
597-
598-
final JsonNode nativeNode = admNode.get("native");
599-
if (nativeNode != null && !nativeNode.isMissingNode()) {
600-
return nativeNode.toString();
601-
}
618+
private ObjectNode updateBidExtWithExtPrebid(PubmaticBidExt pubmaticBidExt, BidType type, ObjectNode extBid) {
619+
final Integer duration = getDuration(pubmaticBidExt);
620+
final boolean inBannerVideo = getInBannerVideo(pubmaticBidExt);
602621

603-
return null;
604-
}
622+
final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder()
623+
.video(duration != null ? ExtBidPrebidVideo.of(duration, null) : null)
624+
.meta(ExtBidPrebidMeta.builder()
625+
.mediaType(inBannerVideo ? BidType.video.getName() : type.getName())
626+
.build())
627+
.build();
605628

606-
private ObjectNode updateBidExtWithExtPrebid(Integer duration, ObjectNode extBid) {
607-
final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder().video(ExtBidPrebidVideo.of(duration, null)).build();
608-
return extBid.set(PREBID, mapper.mapper().valueToTree(extBidPrebid));
629+
return extBid != null
630+
? extBid.set(PREBID, mapper.mapper().valueToTree(extBidPrebid))
631+
: mapper.mapper().createObjectNode().set(PREBID, mapper.mapper().valueToTree(extBidPrebid));
609632
}
610633

611634
private static Integer getDealPriority(PubmaticBidExt bidExt) {
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
package org.prebid.server.bidder.pubmatic.model.response;
22

3-
import com.fasterxml.jackson.annotation.JsonAlias;
43
import com.fasterxml.jackson.annotation.JsonProperty;
54
import lombok.Value;
65

76
@Value(staticConstructor = "of")
87
public class PubmaticBidExt {
98

10-
@JsonProperty("BidType")
11-
@JsonAlias({"bidtype", "bidType"})
12-
Integer bidType;
13-
149
VideoCreativeInfo video;
1510

1611
@JsonProperty("prebiddealpriority")
1712
Integer prebidDealPriority;
1813

1914
String marketplace;
15+
16+
@JsonProperty("ibv")
17+
Boolean inBannerVideo;
2018
}

0 commit comments

Comments
 (0)