Skip to content

New Adapter: ReVantage#4477

Open
v0idxyz wants to merge 4 commits into
prebid:masterfrom
v0idxyz:master
Open

New Adapter: ReVantage#4477
v0idxyz wants to merge 4 commits into
prebid:masterfrom
v0idxyz:master

Conversation

@v0idxyz
Copy link
Copy Markdown

@v0idxyz v0idxyz commented Apr 28, 2026

🔧 Type of changes

  • new bid adapter
  • bid adapter update
  • new feature
  • new analytics adapter
  • new module
  • module update
  • bugfix
  • documentation
  • configuration
  • dependency update
  • tech debt (test coverage, refactorings, etc.)

✨ What's the context?

What's the context for the changes?

🧠 Rationale behind the change

Why did you choose to make these changes? Were there any trade-offs you had to consider?

🔎 New Bid Adapter Checklist

  • verify email contact works
  • NO fully dynamic hostnames
  • geographic host parameters are NOT required
  • direct use of HTTP is prohibited - implement an existing Bidder interface that will do all the job
  • if the ORTB is just forwarded to the endpoint, use the generic adapter - define the new adapter as the alias of the generic adapter
  • cover an adapter configuration with an integration test

🧪 Test plan

How do you know the changes are safe to ship to production?

🏎 Quality check

  • Are your changes following our code style guidelines?
  • Are there any breaking changes in your code?
  • Does your test coverage exceed 90%?
  • Are there any erroneous console logs, debuggers or leftover code in your changes?

@osulzhenko osulzhenko requested review from bukrain and gmiedlar-ox May 5, 2026 15:53
@osulzhenko osulzhenko added the do not merge Not the time for merging yet label May 5, 2026
@osulzhenko osulzhenko requested a review from Fuska1 May 13, 2026 07:38
Comment thread src/main/java/org/prebid/server/bidder/revantage/RevantageBidder.java Outdated
Comment thread src/main/java/org/prebid/server/bidder/revantage/RevantageBidder.java Outdated
if (feedId == null) {
throw new PreBidException("imp %s: missing required param feedId".formatted(imp.getId()));
}
final Imp rewrittenImp = rewriteImpExt(imp, feedId, ext);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rewriteImpExt -> updateImp, rewrittenImp -> updatedImp

Comment on lines +106 to +108
if (wrapper == null || wrapper.getBidder() == null) {
throw new PreBidException("imp %s: missing imp.ext.bidder".formatted(imp.getId()));
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this checks. At this stage, neither the wrapper nor the wrapper.getBidder() can be null

Comment on lines +117 to +129
final ObjectNode bidderNode = mapper.mapper().createObjectNode();
if (StringUtils.isNotBlank(ext.getPlacementId())) {
bidderNode.put("placementId", ext.getPlacementId());
}
if (StringUtils.isNotBlank(ext.getPublisherId())) {
bidderNode.put("publisherId", ext.getPublisherId());
}

final ObjectNode rewritten = mapper.mapper().createObjectNode();
rewritten.put("feedId", feedId);
rewritten.set("bidder", bidderNode);

return imp.toBuilder().ext(rewritten).build();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

        final ObjectNode newExt = mapper.mapper().createObjectNode();
        newExt.put("feedId", feedId);

        final ObjectNode bidderNode = rewritten.putObject("bidder");

        final String placementId = ext.getPlacementId();
        if (StringUtils.isNotBlank(placementId)) {
            bidderNode.put("placementId", placementId);
        }

        final String publisherId = ext.getPublisherId();
        if (StringUtils.isNotBlank(publisherId)) {
            bidderNode.put("publisherId", publisherId);
        }

        return imp.toBuilder().ext(newExt).build();

Comment on lines +138 to +145
return HttpRequest.<BidRequest>builder()
.method(HttpMethod.POST)
.uri(uri)
.headers(headers)
.body(mapper.encodeToBytes(request))
.impIds(collectImpIds(request))
.payload(request)
.build();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use BidderUtil.defaultRequest instead


private static List<BidderBid> extractBids(BidResponse response, BidRequest request) {
if (response == null || CollectionUtils.isEmpty(response.getSeatbid())) {
return List.of();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List.of -> Collections.emptyList

Comment on lines +184 to +196
private static BidType resolveMediaType(Bid bid, List<Imp> imps) {
if (bid.getMtype() != null) {
switch (bid.getMtype()) {
case 1:
return BidType.banner;
case 2:
return BidType.video;
default:
// fall through
}
}

final JsonNode ext = bid.getExt();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor this method:

    private static BidType resolveBidType(Bid bid, List<Imp> imps) {
        return bidTypeFromMtype(bid.getMtype())
                .or(() -> bidTypeFromExt(bid.getExt()))
                .or(() -> bidTypeFromAdm(bid.getAdm()))
                .or(() -> bidTypeFromImp(bid.getImpid(), imps))
                .orElseThrow(() -> new PreBidException(
                        "Cannot determine media type for bid %s on imp %s".formatted(bid.getId(), bid.getImpid())));
    }

    private static Optional<BidType> bidTypeFromMtype(Integer mType) {
        return Optional.ofNullable(switch (mType) {
            case 1 -> BidType.banner;
            case 2 -> BidType.video;
            case null, default -> null;
        });
    }

    private static Optional<BidType> bidTypeFromExt(ObjectNode bidExt) {
        return Optional.ofNullable(bidExt)
                .map(ext -> ext.get("mediaType"))
                .filter(JsonNode::isTextual)
                .map(JsonNode::asText)
                .map(String::toLowerCase)
                .map(mediaType -> switch (mediaType) {
                    case "banner" -> BidType.banner;
                    case "video" -> BidType.video;
                    default -> null;
                });
    }

    private static Optional<BidType> bidTypeFromAdm(String adm) {
        if (StringUtils.isBlank(adm)) {
            return Optional.empty();
        }

        final String trimmed = adm.trim().toUpperCase();
        return trimmed.startsWith("<VAST") || trimmed.startsWith("<?XML")
                ? Optional.of(BidType.video)
                : Optional.empty();
    }

    private static Optional<BidType> bidTypeFromImp(String impId, List<Imp> imps) {
        for (Imp imp : imps) {
            if (!Objects.equals(imp.getId(), impId)) {
                continue;
            }

            final boolean hasBanner = imp.getBanner() != null;
            final boolean hasVideo = imp.getVideo() != null;
            if (hasVideo && !hasBanner) {
                return Optional.of(BidType.video);
            }
            if (hasBanner) {
                return Optional.of(BidType.banner);
            }

            break;
        }

        return Optional.empty();
    }


@Bean("revantageConfigurationProperties")
@ConfigurationProperties("adapters.revantage")
@Validated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for @Validated

Removed detailed class-level documentation and some comments in the makeHttpRequests method.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do not merge Not the time for merging yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants