Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.prebid.server.bidder.connectad;

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.Device;
import com.iab.openrtb.request.Format;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.request.Site;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import io.vertx.core.MultiMap;
Expand Down Expand Up @@ -38,6 +40,7 @@ public class ConnectAdBidder implements Bidder<BidRequest> {
private static final TypeReference<ExtPrebid<?, ExtImpConnectAd>> CONNECTAD_EXT_TYPE_REFERENCE =
new TypeReference<>() {
};
private static final String BIDDER_EXT_KEY = "bidder";
private static final String HTTPS_PREFIX = "https";

private final String endpointUrl;
Expand All @@ -58,7 +61,7 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
for (Imp imp : request.getImp()) {
try {
final ExtImpConnectAd impExt = parseImpExt(imp);
final Imp updatedImp = updateImp(imp, secure, impExt.getSiteId(), impExt.getBidFloor());
final Imp updatedImp = updateImp(imp, secure, impExt);
processedImps.add(updatedImp);
} catch (PreBidException e) {
errors.add(BidderError.badInput(e.getMessage()));
Expand Down Expand Up @@ -91,27 +94,42 @@ private ExtImpConnectAd parseImpExt(Imp imp) {
} catch (IllegalArgumentException e) {
throw new PreBidException("Impression id=%s, has invalid Ext".formatted(imp.getId()));
}
final String siteId = extImpConnectAd.getSiteId();
if (siteId == null) {
if (extImpConnectAd.getSiteId() == null) {
throw new PreBidException("Impression id=%s, has no siteId present".formatted(imp.getId()));
}
return extImpConnectAd;
}

private Imp updateImp(Imp imp, Integer secure, String siteId, BigDecimal bidFloor) {
private Imp updateImp(Imp imp, Integer secure, ExtImpConnectAd extImpConnectAd) {
final BigDecimal bidFloor = extImpConnectAd.getBidFloor();
final boolean isValidBidFloor = BidderUtil.isValidPrice(bidFloor);
return imp.toBuilder()
.banner(updateBanner(imp.getBanner()))
.tagid(siteId)
.tagid(String.valueOf(extImpConnectAd.getSiteId()))
.secure(secure)
.bidfloor(isValidBidFloor ? bidFloor : imp.getBidfloor())
.bidfloorcur(isValidBidFloor ? "USD" : imp.getBidfloorcur())
.ext(modifyImpExt(imp.getExt()))
.build();
}

private ObjectNode modifyImpExt(ObjectNode impExt) {
final ObjectNode modifiedExt = impExt.deepCopy();
final var bidder = impExt.get(BIDDER_EXT_KEY);
if (bidder != null) {
if (bidder.has("networkId")) {
modifiedExt.set("networkId", bidder.get("networkId"));
}
if (bidder.has("siteId")) {
modifiedExt.set("siteId", bidder.get("siteId"));
}
}
return modifiedExt;
}

private static Banner updateBanner(Banner banner) {
if (banner == null) {
throw new PreBidException("We need a Banner Object in the request");
return null;
}

if (banner.getW() != null || banner.getH() != null) {
Expand Down Expand Up @@ -153,13 +171,13 @@ private static MultiMap resolveHeaders(Device device) {
public final Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
try {
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
return Result.withValues(extractBids(bidResponse));
return Result.withValues(extractBids(bidResponse, bidRequest));
} catch (DecodeException | PreBidException e) {
return Result.withError(BidderError.badServerResponse(e.getMessage()));
}
}

private List<BidderBid> extractBids(BidResponse bidResponse) {
private List<BidderBid> extractBids(BidResponse bidResponse, BidRequest bidRequest) {
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
return Collections.emptyList();
}
Expand All @@ -170,7 +188,36 @@ private List<BidderBid> extractBids(BidResponse bidResponse) {
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.map(bid -> BidderBid.of(bid, BidType.banner, bidResponse.getCur()))
.map(bid -> BidderBid.of(bid, getBidType(bid, bidRequest), bidResponse.getCur()))
.toList();
}

private static BidType getBidType(Bid bid, BidRequest bidRequest) {
final Integer mType = bid.getMtype();
if (mType != null) {
return switch (mType) {
case 1 -> BidType.banner;
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> BidType.xNative;
default -> BidType.banner;
};
}

for (Imp imp : bidRequest.getImp()) {
if (imp.getId().equals(bid.getImpid())) {
if (imp.getBanner() != null) {
return BidType.banner;
} else if (imp.getVideo() != null) {
return BidType.video;
} else if (imp.getXNative() != null) {
return BidType.xNative;
} else if (imp.getAudio() != null) {
return BidType.audio;
}
}
}

return BidType.banner;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
public class ExtImpConnectAd {

@JsonProperty("networkId")
String networkId;
Integer networkId;

@JsonProperty("siteId")
String siteId;
Integer siteId;

@JsonProperty("bidfloor")
BigDecimal bidFloor;
Expand Down
13 changes: 10 additions & 3 deletions src/main/resources/bidder-config/connectad.yaml
Comment thread
rtuschkany marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ adapters:
connectad:
# Please uncomment the appropriate endpoint URL for your datacenter
# Europe
endpoint: "http://bidder.connectad.io/API?src=pbs"
endpoint: "https://bidder.connectad.io/API?src=pbs"
ortb-version: "2.6"
# North/South America
# endpoint: "http://bidder-us.connectad.io/API?src=pbs"
# endpoint: "https://bidder-us.connectad.io/API?src=pbs"
# APAC
# endpoint: "http://bidder-apac.connectad.io/API?src=pbs"
# endpoint: "https://bidder-apac.connectad.io/API?src=pbs"
endpoint-compression: gzip
meta-info:
maintainer-email: support@connectad.io
app-media-types:
- banner
- video
- native
- audio
site-media-types:
- banner
- video
- native
- audio
supported-vendors:
vendor-id: 138
usersync:
Expand Down
8 changes: 6 additions & 2 deletions src/main/resources/static/bidder-params/connectad.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "ConnectAd S2S dapter Params",
"title": "ConnectAd S2S Adapter Params",
"description": "A schema which validates params accepted by the ConnectAd Adapter",
"type": "object",
"properties": {
Expand All @@ -20,7 +20,11 @@
},
"bidfloor": {
"type": "number",
"description": "Requests Floorprice"
"description": "Requested Floorprice"
},
"endpointUrl": {
"type": "string",
"description": "Client-side only (Prebid.js): override the bid endpoint URL for testing or a custom datacenter. Ignored by Prebid Server, which always uses its configured endpoint."
}
},
"required": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void makeHttpRequestsShouldReturnErrorWhenImpExtCouldNotBeParsed() {
final BidRequest bidRequest = BidRequest.builder()
.imp(singletonList(Imp.builder()
.id("123")
.banner(Banner.builder().w(300).h(250).build())
.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))
.build()))
.build();
Expand Down Expand Up @@ -109,12 +110,15 @@ public void makeBidsShouldReturnEmptyListWhenBidResponseSeatBidIsNull() throws J
@Test
public void makeBidsShouldReturnBannerBid() throws JsonProcessingException {
// given
final BidRequest bidRequest = BidRequest.builder()
.imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build()))
.build();
final BidderCall<BidRequest> httpCall = givenHttpCall(
BidRequest.builder().imp(singletonList(Imp.builder().id("123").build())).build(),
bidRequest,
mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));

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

// then
assertThat(result.getErrors()).isEmpty();
Expand Down Expand Up @@ -146,7 +150,7 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtHasNoSiteId() {
impBuilder -> impBuilder
.id("123")
.ext(mapper.valueToTree(ExtPrebid.of(null,
ExtImpConnectAd.of("12", null, BigDecimal.ONE)))));
ExtImpConnectAd.of(12, null, BigDecimal.ONE)))));
// when
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);

Expand All @@ -164,7 +168,7 @@ public void impSecureShouldBeOneIfSitePageStartsFromHttps() {
impBuilder -> impBuilder
.id("123")
.ext(mapper.valueToTree(ExtPrebid.of(null,
ExtImpConnectAd.of("12", "1", BigDecimal.ONE)))));
ExtImpConnectAd.of(12, 1, BigDecimal.ONE)))));
// when
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);

Expand All @@ -180,6 +184,32 @@ public void impSecureShouldBeOneIfSitePageStartsFromHttps() {
.containsOnly(1);
}

@Test
public void makeHttpRequestsShouldPropagateSiteIdAndNetworkId() {
// given
final BidRequest bidRequest = givenBidRequest(
impBuilder -> impBuilder
.id("123")
.ext(mapper.valueToTree(ExtPrebid.of(null,
ExtImpConnectAd.of(12345, 67890, BigDecimal.ONE)))));
// when
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.hasSize(1)
.extracting(HttpRequest::getPayload)
.flatExtracting(BidRequest::getImp)
.hasSize(1)
.first()
.satisfies(imp -> {
assertThat(imp.getTagid()).isEqualTo("67890");
assertThat(imp.getExt().get("networkId").asInt()).isEqualTo(12345);
assertThat(imp.getExt().get("siteId").asInt()).isEqualTo(67890);
});
}

private static BidRequest givenBidRequest(
Function<BidRequest.BidRequestBuilder, BidRequest.BidRequestBuilder> bidRequestCustomizer,
Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer) {
Expand All @@ -202,7 +232,7 @@ private static Imp givenImp(Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomiz
.w(14)
.h(15).build())
.ext(mapper.valueToTree(ExtPrebid.of(null,
ExtImpConnectAd.of("12", "12", BigDecimal.ONE)))))
ExtImpConnectAd.of(12, 12, BigDecimal.ONE)))))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@
"imp": [
{
"id": "imp_id",
"secure": 1,
"secure": 0,
"banner": {
"w": 300,
"h": 250
},
"tagid": "15",
"bidfloor": 14.7,
"bidfloorcur": "USD",
"secure": 0,
"ext": {
"tid": "${json-unit.any-string}",
"bidder": {
"networkId": "12",
"siteId": "15",
"bidfloor": 14.7
}
},
"networkId": "12",
"siteId": "15"
}
}
],
Expand All @@ -45,9 +46,7 @@
"USD"
],
"regs": {
"ext": {
"gdpr": 0
}
"gdpr": 0
},
"ext": {
"prebid": {
Expand Down