Skip to content

Commit 274a778

Browse files
authored
Greenbids: Populate AppliedTo and change structure of analytics results in Analytics Tag (#3728)
1 parent c027e3c commit 274a778

File tree

8 files changed

+220
-76
lines changed

8 files changed

+220
-76
lines changed

extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationService.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,24 @@ public GreenbidsInvocationResult createGreenbidsInvocationResult(
3232
final String greenbidsId = UUID.randomUUID().toString();
3333
final boolean isExploration = isExploration(greenbidsConfig, greenbidsId);
3434

35-
final BidRequest updatedBidRequest = isExploration
35+
final List<Imp> updatedImps = updateImps(bidRequest, impsBiddersFilterMap);
36+
37+
final BidRequest updatedBidRequest = isExploration || updatedImps.isEmpty()
3638
? bidRequest
3739
: bidRequest.toBuilder()
38-
.imp(updateImps(bidRequest, impsBiddersFilterMap))
40+
.imp(updatedImps)
3941
.build();
40-
final InvocationAction invocationAction = isExploration
41-
? InvocationAction.no_action
42-
: InvocationAction.update;
43-
final Map<String, Map<String, Boolean>> impsBiddersFilterMapToAnalyticsTag = isExploration
44-
? keepAllBiddersForAnalyticsResult(impsBiddersFilterMap)
45-
: impsBiddersFilterMap;
42+
43+
final InvocationAction invocationAction = updatedImps.isEmpty()
44+
? InvocationAction.reject
45+
: isExploration
46+
? InvocationAction.no_action
47+
: InvocationAction.update;
48+
4649
final Map<String, Ortb2ImpExtResult> ort2ImpExtResultMap = createOrtb2ImpExtForImps(
47-
bidRequest, impsBiddersFilterMapToAnalyticsTag, greenbidsId, isExploration);
50+
bidRequest, impsBiddersFilterMap, greenbidsId, isExploration);
4851
final AnalyticsResult analyticsResult = AnalyticsResult.of(
49-
"success", ort2ImpExtResultMap, null, null);
52+
"success", ort2ImpExtResultMap);
5053

5154
return GreenbidsInvocationResult.of(updatedBidRequest, invocationAction, analyticsResult);
5255
}
@@ -61,10 +64,15 @@ private Boolean isExploration(GreenbidsConfig greenbidsConfig, String greenbidsI
6164

6265
private List<Imp> updateImps(BidRequest bidRequest, Map<String, Map<String, Boolean>> impsBiddersFilterMap) {
6366
return bidRequest.getImp().stream()
67+
.filter(imp -> isImpKept(imp, impsBiddersFilterMap))
6468
.map(imp -> updateImp(imp, impsBiddersFilterMap.get(imp.getId())))
6569
.toList();
6670
}
6771

72+
private boolean isImpKept(Imp imp, Map<String, Map<String, Boolean>> impsBiddersFilterMap) {
73+
return impsBiddersFilterMap.get(imp.getId()).values().stream().anyMatch(isKept -> isKept);
74+
}
75+
6876
private Imp updateImp(Imp imp, Map<String, Boolean> bidderFilterMap) {
6977
return imp.toBuilder()
7078
.ext(updateImpExt(imp.getExt(), bidderFilterMap))
@@ -83,16 +91,6 @@ private ObjectNode updateImpExt(ObjectNode impExt, Map<String, Boolean> bidderFi
8391
return updatedExt;
8492
}
8593

86-
private Map<String, Map<String, Boolean>> keepAllBiddersForAnalyticsResult(
87-
Map<String, Map<String, Boolean>> impsBiddersFilterMap) {
88-
89-
return impsBiddersFilterMap.entrySet().stream()
90-
.collect(Collectors.toMap(
91-
Map.Entry::getKey,
92-
entry -> entry.getValue().entrySet().stream()
93-
.collect(Collectors.toMap(Map.Entry::getKey, e -> true))));
94-
}
95-
9694
private Map<String, Ortb2ImpExtResult> createOrtb2ImpExtForImps(
9795
BidRequest bidRequest,
9896
Map<String, Map<String, Boolean>> impsBiddersFilterMap,

extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/model/result/AnalyticsResult.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,4 @@ public class AnalyticsResult {
1111
String status;
1212

1313
Map<String, Ortb2ImpExtResult> values;
14-
15-
String bidder;
16-
17-
String impId;
1814
}

extra/modules/greenbids-real-time-data/src/main/java/org/prebid/server/hooks/modules/greenbids/real/time/data/v1/GreenbidsRealTimeDataProcessedAuctionRequestHook.java

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import com.iab.openrtb.request.BidRequest;
88
import io.vertx.core.Future;
99
import org.apache.commons.collections4.CollectionUtils;
10+
import org.apache.commons.lang3.BooleanUtils;
11+
import org.prebid.server.analytics.reporter.greenbids.model.ExplorationResult;
1012
import org.prebid.server.analytics.reporter.greenbids.model.Ortb2ImpExtResult;
1113
import org.prebid.server.auction.model.AuctionContext;
1214
import org.prebid.server.exception.PreBidException;
@@ -38,6 +40,7 @@
3840
import org.prebid.server.settings.model.Account;
3941
import org.prebid.server.settings.model.AccountHooksConfiguration;
4042

43+
import java.util.Collection;
4144
import java.util.Collections;
4245
import java.util.List;
4346
import java.util.Map;
@@ -155,55 +158,63 @@ private InvocationResult<AuctionRequestPayload> toInvocationResult(
155158
AnalyticsResult analyticsResult,
156159
InvocationAction action) {
157160

158-
final List<AnalyticsResult> analyticsResults = analyticsResult != null
159-
? Collections.singletonList(analyticsResult)
160-
: Collections.emptyList();
161-
162161
return switch (action) {
163162
case InvocationAction.update -> InvocationResultImpl
164163
.<AuctionRequestPayload>builder()
165164
.status(InvocationStatus.success)
166165
.action(action)
167166
.payloadUpdate(payload -> AuctionRequestPayloadImpl.of(bidRequest))
168-
.analyticsTags(toAnalyticsTags(analyticsResults))
167+
.analyticsTags(toAnalyticsTags(analyticsResult))
169168
.build();
170169
default -> InvocationResultImpl
171170
.<AuctionRequestPayload>builder()
172171
.status(InvocationStatus.success)
173172
.action(action)
174-
.analyticsTags(toAnalyticsTags(analyticsResults))
173+
.analyticsTags(toAnalyticsTags(analyticsResult))
175174
.build();
176175
};
177176
}
178177

179-
private Tags toAnalyticsTags(List<AnalyticsResult> analyticsResults) {
180-
if (CollectionUtils.isEmpty(analyticsResults)) {
178+
private Tags toAnalyticsTags(AnalyticsResult analyticsResult) {
179+
if (analyticsResult == null) {
181180
return null;
182181
}
183182

184183
return TagsImpl.of(Collections.singletonList(ActivityImpl.of(
185184
ACTIVITY,
186185
SUCCESS_STATUS,
187-
toResults(analyticsResults))));
186+
toResults(analyticsResult))));
188187
}
189188

190-
private List<Result> toResults(List<AnalyticsResult> analyticsResults) {
191-
return analyticsResults.stream()
192-
.map(this::toResult)
189+
private List<Result> toResults(AnalyticsResult analyticsResult) {
190+
return analyticsResult.getValues().entrySet().stream()
191+
.map(entry -> toResult(analyticsResult.getStatus(), entry))
193192
.toList();
194193
}
195194

196-
private Result toResult(AnalyticsResult analyticsResult) {
195+
private Result toResult(String status, Map.Entry<String, Ortb2ImpExtResult> entry) {
196+
final String impId = entry.getKey();
197+
final Ortb2ImpExtResult ortb2ImpExtResult = entry.getValue();
198+
final List<String> removedBidders = Optional.ofNullable(ortb2ImpExtResult)
199+
.map(Ortb2ImpExtResult::getGreenbids)
200+
.map(ExplorationResult::getKeptInAuction)
201+
.map(Map::entrySet)
202+
.stream()
203+
.flatMap(Collection::stream)
204+
.filter(e -> BooleanUtils.isFalse(e.getValue()))
205+
.map(Map.Entry::getKey)
206+
.toList();
207+
197208
return ResultImpl.of(
198-
analyticsResult.getStatus(),
199-
toObjectNode(analyticsResult.getValues()),
209+
status,
210+
toObjectNode(entry),
200211
AppliedToImpl.builder()
201-
.bidders(Collections.singletonList(analyticsResult.getBidder()))
202-
.impIds(Collections.singletonList(analyticsResult.getImpId()))
212+
.impIds(Collections.singletonList(impId))
213+
.bidders(removedBidders.isEmpty() ? null: removedBidders)
203214
.build());
204215
}
205216

206-
private ObjectNode toObjectNode(Map<String, Ortb2ImpExtResult> values) {
217+
private ObjectNode toObjectNode(Map.Entry<String, Ortb2ImpExtResult> values) {
207218
return values != null ? mapper.valueToTree(values) : null;
208219
}
209220

extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/core/GreenbidsInvocationServiceTest.java

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenBidRequest;
2525
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenDevice;
2626
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenImpExt;
27+
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenImpExtToFilterAllBidders;
2728

2829
@ExtendWith(MockitoExtension.class)
2930
public class GreenbidsInvocationServiceTest {
@@ -69,7 +70,6 @@ public void createGreenbidsInvocationResultShouldReturnUpdateBidRequestWhenNotEx
6970
assertThat(keptInAuction.get("rubicon")).isTrue();
7071
assertThat(keptInAuction.get("appnexus")).isFalse();
7172
assertThat(keptInAuction.get("pubmatic")).isFalse();
72-
7373
}
7474

7575
@Test
@@ -104,8 +104,87 @@ public void createGreenbidsInvocationResultShouldReturnNoActionWhenExploration()
104104
assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isTrue();
105105
assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull();
106106
assertThat(keptInAuction.get("rubicon")).isTrue();
107-
assertThat(keptInAuction.get("appnexus")).isTrue();
108-
assertThat(keptInAuction.get("pubmatic")).isTrue();
107+
assertThat(keptInAuction.get("appnexus")).isFalse();
108+
assertThat(keptInAuction.get("pubmatic")).isFalse();
109+
}
110+
111+
@Test
112+
public void createGreenbidsInvocationResultShouldReturnRejectWhenAllImpsFiltered() {
113+
// given
114+
final Banner banner = givenBanner();
115+
final Imp imp = Imp.builder()
116+
.id("adunitcodevalue")
117+
.ext(givenImpExt())
118+
.banner(banner)
119+
.build();
120+
final Device device = givenDevice(identity());
121+
final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device);
122+
final Map<String, Map<String, Boolean>> impsBiddersFilterMap = givenFilterMapWithAllFilteredImps();
123+
final GreenbidsConfig greenbidsConfig = givenPartner(1.0);
124+
125+
// when
126+
final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult(
127+
greenbidsConfig, bidRequest, impsBiddersFilterMap);
128+
129+
// then
130+
final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt()
131+
.get("prebid").get("bidder");
132+
final Ortb2ImpExtResult ortb2ImpExtResult = result.getAnalyticsResult().getValues().get("adunitcodevalue");
133+
final Map<String, Boolean> keptInAuction = ortb2ImpExtResult.getGreenbids().getKeptInAuction();
134+
135+
assertThat(result.getInvocationAction()).isEqualTo(InvocationAction.reject);
136+
assertThat(updatedBidRequestExtPrebidBidders.has("rubicon")).isTrue();
137+
assertThat(updatedBidRequestExtPrebidBidders.has("appnexus")).isTrue();
138+
assertThat(updatedBidRequestExtPrebidBidders.has("pubmatic")).isTrue();
139+
assertThat(ortb2ImpExtResult).isNotNull();
140+
assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isTrue();
141+
assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull();
142+
assertThat(keptInAuction.get("rubicon")).isFalse();
143+
assertThat(keptInAuction.get("appnexus")).isFalse();
144+
assertThat(keptInAuction.get("pubmatic")).isFalse();
145+
}
146+
147+
@Test
148+
public void createGreenbidsInvocationResultShouldRemoveImpFromUpdateBidRequestWhenAllBiddersFiltered() {
149+
// given
150+
final Banner banner = givenBanner();
151+
final Imp imp1 = Imp.builder()
152+
.id("adunitcodevalue1")
153+
.ext(givenImpExt())
154+
.banner(banner)
155+
.build();
156+
final Imp imp2 = Imp.builder()
157+
.id("adunitcodevalue2")
158+
.ext(givenImpExtToFilterAllBidders())
159+
.banner(banner)
160+
.build();
161+
final Device device = givenDevice(identity());
162+
final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp1, imp2), device);
163+
final Map<String, Map<String, Boolean>> impsBiddersFilterMap = givenFilterMapWithAllFilteredBiddersInImp();
164+
final GreenbidsConfig greenbidsConfig = givenPartner(0.0);
165+
166+
// when
167+
final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult(
168+
greenbidsConfig, bidRequest, impsBiddersFilterMap);
169+
170+
// then
171+
final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt()
172+
.get("prebid").get("bidder");
173+
final Ortb2ImpExtResult ortb2ImpExtResult = result.getAnalyticsResult().getValues().get("adunitcodevalue1");
174+
final Map<String, Boolean> keptInAuction = ortb2ImpExtResult.getGreenbids().getKeptInAuction();
175+
176+
assertThat(result.getInvocationAction()).isEqualTo(InvocationAction.update);
177+
assertThat(result.getUpdatedBidRequest().getImp()).hasSize(1);
178+
assertThat(updatedBidRequestExtPrebidBidders.has("rubicon")).isTrue();
179+
assertThat(updatedBidRequestExtPrebidBidders.has("appnexus")).isFalse();
180+
assertThat(updatedBidRequestExtPrebidBidders.has("pubmatic")).isFalse();
181+
assertThat(ortb2ImpExtResult).isNotNull();
182+
assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isFalse();
183+
assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull();
184+
assertThat(keptInAuction.get("rubicon")).isTrue();
185+
assertThat(keptInAuction.get("appnexus")).isFalse();
186+
assertThat(keptInAuction.get("pubmatic")).isFalse();
187+
109188
}
110189

111190
private Map<String, Map<String, Boolean>> givenImpsBiddersFilterMap() {
@@ -120,6 +199,34 @@ private Map<String, Map<String, Boolean>> givenImpsBiddersFilterMap() {
120199
return impsBiddersFilterMap;
121200
}
122201

202+
private Map<String, Map<String, Boolean>> givenFilterMapWithAllFilteredImps() {
203+
final Map<String, Boolean> biddersFitlerMap = new HashMap<>();
204+
biddersFitlerMap.put("rubicon", false);
205+
biddersFitlerMap.put("appnexus", false);
206+
biddersFitlerMap.put("pubmatic", false);
207+
208+
final Map<String, Map<String, Boolean>> impsBiddersFilterMap = new HashMap<>();
209+
impsBiddersFilterMap.put("adunitcodevalue", biddersFitlerMap);
210+
211+
return impsBiddersFilterMap;
212+
}
213+
214+
private Map<String, Map<String, Boolean>> givenFilterMapWithAllFilteredBiddersInImp() {
215+
final Map<String, Boolean> biddersFitlerMapForKeptImp = new HashMap<>();
216+
biddersFitlerMapForKeptImp.put("rubicon", true);
217+
biddersFitlerMapForKeptImp.put("appnexus", false);
218+
biddersFitlerMapForKeptImp.put("pubmatic", false);
219+
220+
final Map<String, Boolean> biddersFitlerMapForRemovedImp = new HashMap<>();
221+
biddersFitlerMapForRemovedImp.put("appnexus", false);
222+
223+
final Map<String, Map<String, Boolean>> impsBiddersFilterMap = new HashMap<>();
224+
impsBiddersFilterMap.put("adunitcodevalue1", biddersFitlerMapForKeptImp);
225+
impsBiddersFilterMap.put("adunitcodevalue2", biddersFitlerMapForRemovedImp);
226+
227+
return impsBiddersFilterMap;
228+
}
229+
123230
private GreenbidsConfig givenPartner(Double explorationRate) {
124231
return GreenbidsConfig.of("test-pbuid", 0.60, explorationRate);
125232
}

extra/modules/greenbids-real-time-data/src/test/java/org/prebid/server/hooks/modules/greenbids/real/time/data/util/TestBidRequestProvider.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,23 @@ public static ObjectNode givenImpExt() {
9696
return extNode;
9797
}
9898

99+
public static ObjectNode givenImpExtToFilterAllBidders() {
100+
final ObjectNode bidderNode = MAPPER.createObjectNode();
101+
102+
final ObjectNode appnexusNode = MAPPER.createObjectNode();
103+
appnexusNode.put("placementId", 789);
104+
bidderNode.set("appnexus", appnexusNode);
105+
106+
final ObjectNode prebidNode = MAPPER.createObjectNode();
107+
prebidNode.set("bidder", bidderNode);
108+
109+
final ObjectNode extNode = MAPPER.createObjectNode();
110+
extNode.set("prebid", prebidNode);
111+
extNode.set("tid", TextNode.valueOf("af65045c-2774-44c2-a949-4f42d5c9e179"));
112+
113+
return extNode;
114+
}
115+
99116
public static Device givenDevice(UnaryOperator<Device.DeviceBuilder> deviceCustomizer, String countryAlpha3) {
100117
final String userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36"
101118
+ " (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36";

0 commit comments

Comments
 (0)