diff --git a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java index f2228778feb..afe429b1762 100644 --- a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java +++ b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java @@ -185,13 +185,61 @@ private ExtImpRtbhouse parseImpExt(Imp imp) { } private static Imp modifyImp(Imp imp, Price bidFloorPrice) { + final String existingTagid = imp.getTagid(); + final String tagid = StringUtils.isNotBlank(existingTagid) ? existingTagid : extractTagid(imp); return imp.toBuilder() + .tagid(tagid) .bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency)) .bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue)) .pmp(null) .build(); } + private static String extractTagid(Imp imp) { + final ObjectNode ext = imp.getExt(); + if (ext != null) { + // 1. imp.ext.gpid + final JsonNode gpid = ext.get("gpid"); + if (gpid != null && gpid.isTextual()) { + final String gpidValue = gpid.asText(); + if (StringUtils.isNotBlank(gpidValue)) { + return gpidValue; + } + } + // 2. imp.ext.data.adserver.adslot + final JsonNode data = ext.get("data"); + if (data != null && data.isObject()) { + final JsonNode adserver = data.get("adserver"); + if (adserver != null && adserver.isObject()) { + final JsonNode adslot = adserver.get("adslot"); + if (adslot != null && adslot.isTextual()) { + final String adslotValue = adslot.asText(); + if (StringUtils.isNotBlank(adslotValue)) { + return adslotValue; + } + } + } + } + // 3. imp.ext.data.pbadslot + if (data != null && data.isObject()) { + final JsonNode pbadslot = data.get("pbadslot"); + if (pbadslot != null && pbadslot.isTextual()) { + final String pbadslotValue = pbadslot.asText(); + if (StringUtils.isNotBlank(pbadslotValue)) { + return pbadslotValue; + } + } + } + } + // 4. imp.id + final String impId = imp.getId(); + if (StringUtils.isNotBlank(impId)) { + return impId; + } + // 5. empty (not set) + return null; + } + private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) { final List brCur = bidRequest.getCur(); final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); diff --git a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java index fe10dad45e3..b0f5b7a247c 100644 --- a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java @@ -518,6 +518,147 @@ public void makeHttpRequestsShouldAlwaysRemovePmpField() { .containsOnlyNulls(); } + @Test + public void makeHttpRequestsShouldSetTagidFromGpid() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("gpid_value"); + } + + @Test + public void makeHttpRequestsShouldSetTagidFromAdserverAdslot() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode() + .set("adserver", mapper.createObjectNode().put("adslot", "adslot_value"))))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("adslot_value"); + } + + @Test + public void makeHttpRequestsShouldSetTagidFromPbadslot() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode() + .put("pbadslot", "pbadslot_value")))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("pbadslot_value"); + } + + @Test + public void makeHttpRequestsShouldSetTagidFromImpIdWhenNoOtherFields() { + // given + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id("imp123"), + identity()); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("imp123"); + } + + @Test + public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id(null) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() + .publisherId("publisherId") + .region("region") + .build()))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsOnlyNulls(); + } + + @Test + public void makeHttpRequestsShouldPreserveExistingTagid() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .tagid("existing_tagid") + .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("existing_tagid"); + } + private static BidResponse givenBidResponse(Function bidCustomizer) { return BidResponse.builder() .cur("USD") @@ -562,4 +703,12 @@ private static Imp givenImp(Function impCustomiz .build())))) .build(); } + + private static ObjectNode givenRtbhouseExt(Function extCustomizer) { + final ObjectNode extNode = (ObjectNode) mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() + .publisherId("publisherId") + .region("region") + .build())); + return extCustomizer.apply(extNode); + } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json index e63afde3937..28d0438942f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json @@ -13,7 +13,8 @@ "bidder": { "publisherId": "publisherId" } - } + }, + "tagid": "imp_id" } ], "source": {