diff --git a/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java b/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java index df94eb3222f..7accd40452f 100644 --- a/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java +++ b/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java @@ -99,6 +99,7 @@ public Result>> makeHttpRequests(BidRequest request) { .gdprApplies(requestUtil.getGdprApplies(request.getRegs())) .consent(requestUtil.getConsent(extUser)) .currency(currency) + .eids(requestUtil.getEids(extUser, mapper)) .build()); final MultiMap headers = httpUtil.buildAdformHeaders( diff --git a/src/main/java/org/prebid/server/bidder/adform/AdformHttpUtil.java b/src/main/java/org/prebid/server/bidder/adform/AdformHttpUtil.java index a95124cdcd1..79bb67bb77c 100644 --- a/src/main/java/org/prebid/server/bidder/adform/AdformHttpUtil.java +++ b/src/main/java/org/prebid/server/bidder/adform/AdformHttpUtil.java @@ -102,6 +102,11 @@ String buildAdformUrl(UrlParameters parameters) { params.add("gdpr=" + parameters.getGdprApplies()); params.add("gdpr_consent=" + parameters.getConsent()); + final String eids = parameters.getEids(); + if (StringUtils.isNotEmpty(eids)) { + params.add("eids=" + eids); + } + final List encodedMids = new ArrayList<>(); final List masterTagIds = parameters.getMasterTagIds(); final List keyValues = parameters.getKeyValues(); diff --git a/src/main/java/org/prebid/server/bidder/adform/AdformRequestUtil.java b/src/main/java/org/prebid/server/bidder/adform/AdformRequestUtil.java index d99ad25079f..335f6627cd5 100644 --- a/src/main/java/org/prebid/server/bidder/adform/AdformRequestUtil.java +++ b/src/main/java/org/prebid/server/bidder/adform/AdformRequestUtil.java @@ -1,12 +1,21 @@ package org.prebid.server.bidder.adform; import com.iab.openrtb.request.Regs; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.bidder.adform.model.AdformDigitrust; import org.prebid.server.bidder.adform.model.AdformDigitrustPrivacy; +import org.prebid.server.json.JacksonMapper; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtUser; import org.prebid.server.proto.openrtb.ext.request.ExtUserDigiTrust; +import org.prebid.server.proto.openrtb.ext.request.ExtUserEid; +import org.prebid.server.proto.openrtb.ext.request.ExtUserEidUid; + +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Util class to help {@link org.prebid.server.bidder.adform.AdformBidder} and @@ -47,4 +56,27 @@ AdformDigitrust getAdformDigitrust(ExtUser extUser) { AdformDigitrustPrivacy.of(extUserDigiTrust.getPref() != 0)) : null; } + + /** + * Retrieves eids from user.ext.eids and in case of any exception or invalid values return empty collection. + */ + String getEids(ExtUser extUser, JacksonMapper mapper) { + final List eids = extUser != null ? extUser.getEids() : null; + final Map> eidsMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(eids)) { + for (ExtUserEid eid : eids) { + final Map uidMap = eidsMap.computeIfAbsent(eid.getSource(), + ignored -> new HashMap<>()); + for (ExtUserEidUid uid : eid.getUids()) { + uidMap.put(uid.getId(), uid.getAtype()); + } + } + } + + final String encodedEids = mapper.encode(eidsMap); + + return ObjectUtils + .defaultIfNull(Base64.getUrlEncoder().withoutPadding().encodeToString(encodedEids.getBytes()), + ""); + } } diff --git a/src/main/java/org/prebid/server/bidder/adform/model/UrlParameters.java b/src/main/java/org/prebid/server/bidder/adform/model/UrlParameters.java index dda9c930a27..16156305fd7 100644 --- a/src/main/java/org/prebid/server/bidder/adform/model/UrlParameters.java +++ b/src/main/java/org/prebid/server/bidder/adform/model/UrlParameters.java @@ -32,4 +32,6 @@ public class UrlParameters { String consent; String currency; + + String eids; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtUserEidUid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtUserEidUid.java index ec0708e076b..a1cec741761 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtUserEidUid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtUserEidUid.java @@ -12,5 +12,7 @@ public class ExtUserEidUid { String id; + Integer atype; + ExtUserEidUidExt ext; } diff --git a/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java b/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java index c9d2604fed1..2ff76862cda 100644 --- a/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java @@ -26,6 +26,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtUser; import org.prebid.server.proto.openrtb.ext.request.ExtUserDigiTrust; +import org.prebid.server.proto.openrtb.ext.request.ExtUserEid; +import org.prebid.server.proto.openrtb.ext.request.ExtUserEidUid; import org.prebid.server.proto.openrtb.ext.request.adform.ExtImpAdform; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; @@ -66,6 +68,8 @@ public void makeHttpRequestsShouldReturnHttpRequestWithoutErrors() { .ext(ExtUser.builder() .consent("consent") .digitrust(ExtUserDigiTrust.of("id", 123, 1)) + .eids(singletonList(ExtUserEid.of("test.com", "some_user_id", + singletonList(ExtUserEidUid.of("uId", 1, null)), null))) .build()) .build()) .device(Device.builder().ua("ua").ip("ip").ifa("ifaId").build()) @@ -81,8 +85,9 @@ public void makeHttpRequestsShouldReturnHttpRequestWithoutErrors() { assertThat(result.getValue()).hasSize(1) .extracting(HttpRequest::getUri) .containsExactly( - "http://adform.com/openrtb2d?CC=1&adid=ifaId&fd=1&gdpr=1&gdpr_consent=consent&ip=ip&pt=gross" - + "&rp=4&stid=tid&bWlkPTE1JnJjdXI9VVNEJm1rdj1jb2xvcjpyZWQmbWt3PXJlZA"); + "http://adform.com/openrtb2d?CC=1&adid=ifaId&eids=eyJ0ZXN0LmNvbSI6eyJ1SWQiOjF9fQ&fd=1&gdpr=1" + + "&gdpr_consent=consent&ip=ip&pt=gross&rp=4&stid=tid" + + "&bWlkPTE1JnJjdXI9VVNEJm1rdj1jb2xvcjpyZWQmbWt3PXJlZA"); assertThat(result.getValue()).extracting(HttpRequest::getMethod).containsExactly(HttpMethod.GET); assertThat(result.getValue()) @@ -172,6 +177,15 @@ public void makeHttpRequestsShouldReturnHttpsUrlIfAtLeastOneImpIsSecured() { .build(), Imp.builder().build())) .source(Source.builder().tid("tid").build()) + .user(User.builder() + .buyeruid("buyeruid") + .ext(ExtUser.builder() + .consent("consent") + .digitrust(ExtUserDigiTrust.of("id", 123, 1)) + .eids(singletonList(ExtUserEid.of("test.com", "some_user_id", + singletonList(ExtUserEidUid.of("uId", 1, null)), null))) + .build()) + .build()) .build(); // when @@ -180,8 +194,8 @@ public void makeHttpRequestsShouldReturnHttpsUrlIfAtLeastOneImpIsSecured() { // then assertThat(result.getValue()).hasSize(1) .extracting(HttpRequest::getUri) - .containsExactly("https://adform.com/openrtb2d?CC=1&fd=1&gdpr=&gdpr_consent=&ip=&rp=4&" - + "stid=tid&bWlkPTE1JnJjdXI9VVNE"); + .containsExactly("https://adform.com/openrtb2d?CC=1&eids=eyJ0ZXN0LmNvbSI6eyJ1SWQiOjF9fQ&fd=1&gdpr=" + + "&gdpr_consent=consent&ip=&rp=4&stid=tid&bWlkPTE1JnJjdXI9VVNE"); } @Test diff --git a/src/test/java/org/prebid/server/bidder/adform/AdformHttpUtilTest.java b/src/test/java/org/prebid/server/bidder/adform/AdformHttpUtilTest.java index 558dbc24b91..1ce1969c563 100644 --- a/src/test/java/org/prebid/server/bidder/adform/AdformHttpUtilTest.java +++ b/src/test/java/org/prebid/server/bidder/adform/AdformHttpUtilTest.java @@ -135,12 +135,14 @@ public void buildAdformUrlShouldReturnCorrectUrl() { .consent("consent") .secure(false) .currency("USD") + .eids("eyJ0ZXN0LmNvbSI6eyJvdGh") .build()); // then // bWlkPTE1 is Base64 encoded mid=15 and bWlkPTE2 encoded mid=16, so bWlkPTE1&bWlkPTE2 = mid=15&mid=16 assertThat(url).isEqualTo( - "http://adx.adform.net/adx?CC=1&adid=adId&fd=1&gdpr=1&gdpr_consent=consent&ip=ip&pt=gross&rp=4" + "http://adx.adform.net/adx?CC=1&adid=adId&eids=eyJ0ZXN0LmNvbSI6eyJvdGh&" + + "fd=1&gdpr=1&gdpr_consent=consent&ip=ip&pt=gross&rp=4" + "&stid=tid&bWlkPTE1JnJjdXI9VVNEJm1rdj1jb2xvcjpyZWQmbWt3PXJlZA" + "&bWlkPTE2JnJjdXI9VVNEJm1rdj1hZ2U6MzAtNDAmbWt3PWJsdWU"); } @@ -291,4 +293,32 @@ public void buildAdformUrlShouldHasGrossPtParamIfGrossAndNetAndNotValidPriceType .isEqualTo("http://adx.adform.net/adx?CC=1&fd=1&gdpr=&gdpr_consent=&ip=ip&pt=gross&rp=4" + "&stid=tid&bWlkPTE1JnJjdXI9VVNE&bWlkPTE2JnJjdXI9VVNE"); } + + @Test + public void buildAdformUrlShouldNotContainEidsParamIfEmptyEids() { + // when + final String url = httpUtil.buildAdformUrl( + UrlParameters.builder() + .masterTagIds(asList(15L, 16L)) + .keyValues(asList("color:red", "age:30-40")) + .keyWords(asList("red", "blue")) + .priceTypes(singletonList("gross")) + .endpointUrl("http://adx.adform.net/adx") + .tid("tid") + .ip("ip") + .advertisingId("adId") + .gdprApplies("1") + .consent("consent") + .secure(false) + .currency("USD") + .eids(null) + .build()); + + // then + // bWlkPTE1 is Base64 encoded mid=15 and bWlkPTE2 encoded mid=16, so bWlkPTE1&bWlkPTE2 = mid=15&mid=16 + assertThat(url).isEqualTo( + "http://adx.adform.net/adx?CC=1&adid=adId&fd=1&gdpr=1&gdpr_consent=consent&ip=ip&pt=gross&rp=4" + + "&stid=tid&bWlkPTE1JnJjdXI9VVNEJm1rdj1jb2xvcjpyZWQmbWt3PXJlZA" + + "&bWlkPTE2JnJjdXI9VVNEJm1rdj1hZ2U6MzAtNDAmbWt3PWJsdWU"); + } } diff --git a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java index 483fefe5af7..cb199d60acf 100644 --- a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java @@ -754,7 +754,8 @@ public void makeHttpRequestsShouldCreateUserExtTpIdWithAdServerEidSource() { .ext(ExtUser.builder() .eids(singletonList(ExtUserEid.of("adserver.org", null, singletonList( - ExtUserEidUid.of("adServerUid", ExtUserEidUidExt.of("TDID"))), null))) + ExtUserEidUid.of("adServerUid", null, ExtUserEidUidExt.of("TDID"))), + null))) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -772,7 +773,8 @@ public void makeHttpRequestsShouldCreateUserExtTpIdWithAdServerEidSource() { .eids(singletonList(ExtUserEid.of( "adserver.org", null, - singletonList(ExtUserEidUid.of("adServerUid", ExtUserEidUidExt.of("TDID"))), + singletonList(ExtUserEidUid.of("adServerUid", null, + ExtUserEidUidExt.of("TDID"))), null))) .build(), RubiconUserExt.builder() @@ -786,13 +788,13 @@ public void makeHttpRequestsShouldCreateUserExtTpIdForFirstLiveintentAndAdserver final ObjectNode uidExt = mapper.createObjectNode(); uidExt.putArray("segments").add("999").add("888"); final ExtUserEid liveintentUid1 = ExtUserEid.of("liveintent.com", null, - singletonList(ExtUserEidUid.of("liveintentUid1", null)), uidExt); + singletonList(ExtUserEidUid.of("liveintentUid1", null, null)), uidExt); final ExtUserEid liveintentUid2 = ExtUserEid.of("liveintent.com", null, - singletonList(ExtUserEidUid.of("liveintentUid2", null)), null); + singletonList(ExtUserEidUid.of("liveintentUid2", null, null)), null); final ExtUserEid adserverUid = ExtUserEid.of("adserver.org", null, - singletonList(ExtUserEidUid.of("adServerUid", ExtUserEidUidExt.of("TDID"))), null); + singletonList(ExtUserEidUid.of("adServerUid", null, ExtUserEidUidExt.of("TDID"))), null); final ExtUserEid notSpecialSource = ExtUserEid.of("notSpecialSource", null, - singletonList(ExtUserEidUid.of("notSpecialSource", ExtUserEidUidExt.of("TDID"))), null); + singletonList(ExtUserEidUid.of("notSpecialSource", null, ExtUserEidUidExt.of("TDID"))), null); final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() .eids(Arrays.asList(liveintentUid1, liveintentUid2, adserverUid, notSpecialSource)) @@ -832,7 +834,7 @@ public void makeHttpRequestsShouldCreateUserExtTpIdWithLiveintentEidSourceAndRpF .ext(ExtUser.builder() .eids(singletonList(ExtUserEid.of("liveintent.com", null, singletonList( - ExtUserEidUid.of("liveintentUid", null)), + ExtUserEidUid.of("liveintentUid", null, null)), uidExt))) .build()) .build()), @@ -852,7 +854,7 @@ public void makeHttpRequestsShouldCreateUserExtTpIdWithLiveintentEidSourceAndRpF .containsOnly(jacksonMapper.fillExtension( ExtUser.builder() .eids(singletonList(ExtUserEid.of("liveintent.com", null, - singletonList(ExtUserEidUid.of("liveintentUid", null)), uidExt))) + singletonList(ExtUserEidUid.of("liveintentUid", null, null)), uidExt))) .build(), RubiconUserExt.builder() .tpid(singletonList(ExtUserTpIdRubicon.of("liveintent.com", "liveintentUid"))) @@ -866,7 +868,7 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithAdServerEidSourceIfEid final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() .eids(singletonList(ExtUserEid.of("adserver.org", null, - singletonList(ExtUserEidUid.of("id", null)), null))) + singletonList(ExtUserEidUid.of("id", null, null)), null))) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -882,7 +884,7 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithAdServerEidSourceIfEid .containsOnly(jacksonMapper.fillExtension( ExtUser.builder() .eids(singletonList(ExtUserEid.of("adserver.org", null, - singletonList(ExtUserEidUid.of("id", null)), null))) + singletonList(ExtUserEidUid.of("id", null, null)), null))) .build(), RubiconUserExt.builder() .tpid(null) @@ -895,7 +897,7 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithAdServerEidSourceIfExt final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() .eids(singletonList(ExtUserEid.of("adserver.org", null, - singletonList(ExtUserEidUid.of("id", ExtUserEidUidExt.of(null))), null))) + singletonList(ExtUserEidUid.of("id", null, ExtUserEidUidExt.of(null))), null))) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -910,7 +912,7 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithAdServerEidSourceIfExt .extracting(request -> request.getUser().getExt()) .containsOnly(ExtUser.builder() .eids(singletonList(ExtUserEid.of("adserver.org", null, - singletonList(ExtUserEidUid.of("id", ExtUserEidUidExt.of(null))), null))) + singletonList(ExtUserEidUid.of("id", null, ExtUserEidUidExt.of(null))), null))) .build()); } @@ -921,10 +923,10 @@ public void makeHttpRequestsShouldCreateUserExtLiverampId() { .eids(asList( ExtUserEid.of("liveramp.com", null, asList( - ExtUserEidUid.of("firstId", null), - ExtUserEidUid.of("ignored", null)), null), + ExtUserEidUid.of("firstId", null, null), + ExtUserEidUid.of("ignored", null, null)), null), ExtUserEid.of("liveramp.com", null, - singletonList(ExtUserEidUid.of("ignored", null)), null))) + singletonList(ExtUserEidUid.of("ignored", null, null)), null))) .build(); final BidRequest bidRequest = givenBidRequest( builder -> builder.user(User.builder().ext(extUser).build()), @@ -976,7 +978,8 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithUnknownEidSource() { final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() .eids(singletonList(ExtUserEid.of("unknownSource", null, - singletonList(ExtUserEidUid.of("id", ExtUserEidUidExt.of("eidUidId"))), null))) + singletonList(ExtUserEidUid.of("id", null, ExtUserEidUidExt.of("eidUidId"))), + null))) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -991,7 +994,7 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithUnknownEidSource() { .extracting(request -> request.getUser().getExt()) .containsOnly(ExtUser.builder() .eids(singletonList(ExtUserEid.of("unknownSource", null, - singletonList(ExtUserEidUid.of("id", ExtUserEidUidExt.of("eidUidId"))), null))) + singletonList(ExtUserEidUid.of("id", null, ExtUserEidUidExt.of("eidUidId"))), null))) .build()); } diff --git a/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughBidderTest.java b/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughBidderTest.java index f3845bbb856..acd1bd4f4f7 100644 --- a/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughBidderTest.java @@ -165,8 +165,8 @@ public void makeHttpRequestsShouldReturnRequestWithCorrectUriAndHeadersDefaultPa throws JsonProcessingException { // given final List uids = Arrays.asList( - ExtUserEidUid.of("first", null), - ExtUserEidUid.of("second", null)); + ExtUserEidUid.of("first", null, null), + ExtUserEidUid.of("second", null, null)); final ExtUserEid extUserEid = ExtUserEid.of("adserver.org", null, uids, null); final ExtUser extUser = ExtUser.builder() .consent("consent") diff --git a/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughRequestUtilTest.java b/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughRequestUtilTest.java index 92dd548b590..8c4d80347ff 100644 --- a/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughRequestUtilTest.java +++ b/src/test/java/org/prebid/server/bidder/sharethrough/SharethroughRequestUtilTest.java @@ -123,8 +123,8 @@ public void getUserInfoShouldReturnUserInfoWithTtdUidFromFirstExtUserEidUid() { // given final String consent = "con"; final List uids = Arrays.asList( - ExtUserEidUid.of("first", null), - ExtUserEidUid.of("second", null)); + ExtUserEidUid.of("first", null, null), + ExtUserEidUid.of("second", null, null)); final ExtUserEid extUserEid = ExtUserEid.of("adserver.org", null, uids, null); final ExtUser extUser = ExtUser.builder() @@ -142,13 +142,13 @@ public void getUserInfoShouldReturnUserInfoWithTtdUidFromFirstExtUserEidUid() { public void getUserInfoShouldReturnUserInfoWithTtdUidFromFirstExtUserEidUidFromSecondExtUserEid() { // given final List uidsFromFirst = Arrays.asList( - ExtUserEidUid.of("firstFromFirst", null), - ExtUserEidUid.of("secondFromFirst", null)); + ExtUserEidUid.of("firstFromFirst", null, null), + ExtUserEidUid.of("secondFromFirst", null, null)); final ExtUserEid firstExtUserEid = ExtUserEid.of("badSource", null, uidsFromFirst, null); final List uidsFromSecond = Arrays.asList( - ExtUserEidUid.of("firstFromSecond", null), - ExtUserEidUid.of("secondFromSecond", null)); + ExtUserEidUid.of("firstFromSecond", null, null), + ExtUserEidUid.of("secondFromSecond", null, null)); final ExtUserEid secondExtUserEid = ExtUserEid.of("adserver.org", null, uidsFromSecond, null); final ExtUser extUser = ExtUser.builder() diff --git a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java index 44b3bc11048..5f2331643c7 100644 --- a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java @@ -1663,7 +1663,7 @@ public void validateShouldReturnValidationMessageWhenEidUidIdIsMissing() { .user(User.builder() .ext(ExtUser.builder() .eids(singletonList(ExtUserEid.of("source", null, - singletonList(ExtUserEidUid.of(null, null)), null))) + singletonList(ExtUserEidUid.of(null, null, null)), null))) .build()) .build()) .build(); @@ -1684,9 +1684,9 @@ public void validateShouldReturnValidationMessageWhenEidSourceIsNotUnique() { .ext(ExtUser.builder() .eids(asList( ExtUserEid.of("source", null, - singletonList(ExtUserEidUid.of("id1", null)), null), + singletonList(ExtUserEidUid.of("id1", null, null)), null), ExtUserEid.of("source", null, - singletonList(ExtUserEidUid.of("id2", null)), null))) + singletonList(ExtUserEidUid.of("id2", null, null)), null))) .build()) .build()) .build();