Skip to content

Commit

Permalink
Rubicon: Eid enhancement (#1701)
Browse files Browse the repository at this point in the history
  • Loading branch information
CTMBNara authored Feb 10, 2022
1 parent ca7256b commit 32fc446
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 11 deletions.
52 changes: 41 additions & 11 deletions src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public class RubiconBidder implements Bidder<BidRequest> {
private static final String ADSERVER_EID = "adserver.org";
private static final String LIVEINTENT_EID = "liveintent.com";
private static final String LIVERAMP_EID = "liveramp.com";
private static final String SOURCE_RUBICON = "rubiconproject.com";

private static final String FPD_GPID_FIELD = "gpid";
private static final String FPD_SECTIONCAT_FIELD = "sectioncat";
Expand All @@ -144,6 +145,7 @@ public class RubiconBidder implements Bidder<BidRequest> {
private static final String PREBID_EXT = "prebid";

private static final String PPUID_STYPE = "ppuid";
private static final String OTHER_STYPE = "other";
private static final String SHA256EMAIL_STYPE = "sha256email";
private static final String DMP_STYPE = "dmp";
private static final String XAPI_CURRENCY = "USD";
Expand Down Expand Up @@ -179,7 +181,7 @@ public RubiconBidder(String endpoint,
JacksonMapper mapper) {

this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpoint));
this.supportedVendors = new HashSet<>(supportedVendors);
this.supportedVendors = Set.copyOf(Objects.requireNonNull(supportedVendors));
this.generateBidId = generateBidId;
this.currencyConversionService = Objects.requireNonNull(currencyConversionService);
this.mapper = Objects.requireNonNull(mapper);
Expand All @@ -194,12 +196,11 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequ

final List<Imp> imps = extractValidImps(bidRequest, errors);
if (CollectionUtils.isEmpty(imps)) {
errors.add(BidderError.of("There are no valid impressions to create bid request to rubicon bidder",
BidderError.Type.bad_input));
return Result.of(Collections.emptyList(), errors);
errors.add(BidderError.badInput("There are no valid impressions to create bid request to rubicon bidder"));
return Result.withErrors(errors);
}
final Map<Imp, ExtPrebid<ExtImpPrebid, ExtImpRubicon>> impToImpExt =
parseRubiconImpExts(imps, errors);

final Map<Imp, ExtPrebid<ExtImpPrebid, ExtImpRubicon>> impToImpExt = parseRubiconImpExts(imps, errors);
final String impLanguage = firstImpExtLanguage(impToImpExt.values());
final String uri = makeUri(bidRequest);

Expand Down Expand Up @@ -270,9 +271,8 @@ private static boolean isValidType(Imp imp) {

private BidderError impTypeErrorMessage(Imp imp) {
final BidType type = resolveExpectedBidType(imp);
return BidderError.of(
String.format("Impression with id %s rejected with invalid type `%s`." + " Allowed types are banner and"
+ " video.", imp.getId(), type != null ? type.name() : "unknown"), BidderError.Type.bad_input);
return BidderError.badInput(String.format("Impression with id %s rejected with invalid type `%s`."
+ " Allowed types are banner and video.", imp.getId(), type != null ? type.name() : "unknown"));
}

private static BidType resolveExpectedBidType(Imp imp) {
Expand Down Expand Up @@ -938,6 +938,8 @@ private User makeUser(User user, ExtImpRubicon rubiconImpExt) {
final ExtUser extUser = user != null ? user.getExt() : null;
final String resolvedId = userId == null ? resolveUserId(extUser) : null;
final List<ExtUserEid> extUserEids = extUser != null ? extUser.getEids() : null;
final String userBuyeruid = user != null ? user.getBuyeruid() : null;
final String resolvedBuyeruid = userBuyeruid != null ? userBuyeruid : resolveBuyeruidFromEids(extUserEids);
final Map<String, List<ExtUserEid>> sourceToUserEidExt = extUser != null
? specialExtUserEids(extUserEids)
: null;
Expand All @@ -952,8 +954,13 @@ private User makeUser(User user, ExtImpRubicon rubiconImpExt) {
final ObjectNode userExtData = extUser != null ? extUser.getData() : null;
final String liverampId = extractLiverampId(sourceToUserEidExt);

if (userExtRp == null && userExtTpIds == null && userExtData == null && liverampId == null
&& resolvedId == null && !hasStypeToRemove) {
if (userExtRp == null
&& userExtTpIds == null
&& userExtData == null
&& liverampId == null
&& resolvedId == null
&& Objects.equals(userBuyeruid, resolvedBuyeruid)
&& !hasStypeToRemove) {
return user;
}

Expand All @@ -975,6 +982,7 @@ private User makeUser(User user, ExtImpRubicon rubiconImpExt) {

return userBuilder
.id(ObjectUtils.defaultIfNull(resolvedId, userId))
.buyeruid(resolvedBuyeruid)
.gender(null)
.yob(null)
.geo(null)
Expand Down Expand Up @@ -1041,6 +1049,28 @@ private static ExtUserEidUid cleanExtUserEidUidStype(ExtUserEidUid extUserEidUid
ExtUserEidUidExt.of(extUserEidUidExt.getRtiPartner(), null));
}

private static String resolveBuyeruidFromEids(List<ExtUserEid> eids) {
return CollectionUtils.emptyIfNull(eids).stream()
.filter(Objects::nonNull)
.filter(eid -> SOURCE_RUBICON.equals(eid.getSource()))
.map(ExtUserEid::getUids)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.filter(RubiconBidder::validateExtUserEidUidForUserBuyeruid)
.map(ExtUserEidUid::getId)
.findFirst()
.orElse(null);

}

private static boolean validateExtUserEidUidForUserBuyeruid(ExtUserEidUid uid) {
final ExtUserEidUidExt uidExt = ObjectUtil.getIfNotNull(uid, ExtUserEidUid::getExt);
final String uidExtStype = ObjectUtil.getIfNotNull(uidExt, ExtUserEidUidExt::getStype);

return StringUtils.equalsAny(uidExtStype, PPUID_STYPE, OTHER_STYPE);
}

private static Map<String, List<ExtUserEid>> specialExtUserEids(List<ExtUserEid> eids) {
if (CollectionUtils.isEmpty(eids)) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,100 @@ public void makeHttpRequestsShouldNotCreateUserIfVisitorAndConsentNotPresent() {
.containsOnly((User) null);
}

@Test
public void makeHttpRequestsShouldUseUserBuyeruidIfPresent() {
// given
final BidRequest bidRequest = givenBidRequest(
builder -> builder.user(User.builder()
.buyeruid("buyeruid")
.ext(ExtUser.builder()
.eids(singletonList(ExtUserEid.of(
"rubiconproject.com",
null,
singletonList(ExtUserEidUid.of(
"extUserEidUidId",
null,
ExtUserEidUidExt.of(null, "ppuid")
)),
null)))
.build())
.build()),
builder -> builder.video(Video.builder().build()), identity());

// when
final Result<List<HttpRequest<BidRequest>>> result = rubiconBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getValue())
.extracting(HttpRequest::getPayload)
.extracting(BidRequest::getUser)
.extracting(User::getBuyeruid)
.containsExactly("buyeruid");
assertThat(result.getErrors()).isEmpty();
}

@Test
public void makeHttpRequestsShouldUseUidIdIfUserBuyeruidAbsentAndSpecialEidSourceAndStypeIsPpuid() {
// given
final BidRequest bidRequest = givenBidRequest(
builder -> builder.user(User.builder()
.ext(ExtUser.builder()
.eids(singletonList(ExtUserEid.of(
"rubiconproject.com",
null,
singletonList(ExtUserEidUid.of(
"extUserEidUidId",
null,
ExtUserEidUidExt.of(null, "ppuid")
)),
null)))
.build())
.build()),
builder -> builder.video(Video.builder().build()), identity());

// when
final Result<List<HttpRequest<BidRequest>>> result = rubiconBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getValue())
.extracting(HttpRequest::getPayload)
.extracting(BidRequest::getUser)
.extracting(User::getBuyeruid)
.containsExactly("extUserEidUidId");
assertThat(result.getErrors()).isEmpty();
}

@Test
public void makeHttpRequestsShouldUseUidIdIfUserBuyeruidAbsentAndSpecialEidSourceAndStypeIsOther() {
// given
final BidRequest bidRequest = givenBidRequest(
builder -> builder.user(User.builder()
.ext(ExtUser.builder()
.eids(singletonList(ExtUserEid.of(
"rubiconproject.com",
null,
singletonList(ExtUserEidUid.of(
"extUserEidUidId",
null,
ExtUserEidUidExt.of(null, "other")
)),
null)))
.build())
.build()),
builder -> builder.video(Video.builder().build()), identity());

// when
final Result<List<HttpRequest<BidRequest>>> result = rubiconBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getValue())
.extracting(HttpRequest::getPayload)
.extracting(BidRequest::getUser)
.extracting(User::getBuyeruid)
.containsExactly("extUserEidUidId");
assertThat(result.getErrors()).isEmpty();
}

@Test
public void makeHttpRequestsShouldCreateUserExtTpIdWithAdServerEidSource() {
// given
Expand Down

0 comments on commit 32fc446

Please sign in to comment.