Skip to content

Commit 7d5dae5

Browse files
authored
GumGum: Add slot param (prebid#1446)
1 parent 140ccf1 commit 7d5dae5

5 files changed

Lines changed: 137 additions & 27 deletions

File tree

src/main/java/org/prebid/server/bidder/gumgum/GumgumBidder.java

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import io.vertx.core.http.HttpMethod;
1616
import org.apache.commons.collections4.CollectionUtils;
1717
import org.apache.commons.lang3.ArrayUtils;
18+
import org.apache.commons.lang3.ObjectUtils;
1819
import org.apache.commons.lang3.StringUtils;
1920
import org.prebid.server.bidder.Bidder;
21+
import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgumBanner;
2022
import org.prebid.server.bidder.model.BidderBid;
2123
import org.prebid.server.bidder.model.BidderError;
2224
import org.prebid.server.bidder.model.HttpCall;
@@ -37,6 +39,7 @@
3739
import java.util.Arrays;
3840
import java.util.Collection;
3941
import java.util.Collections;
42+
import java.util.Comparator;
4043
import java.util.List;
4144
import java.util.Objects;
4245
import java.util.stream.Collectors;
@@ -71,13 +74,13 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequ
7174
}
7275

7376
return Result.of(Collections.singletonList(
74-
HttpRequest.<BidRequest>builder()
75-
.method(HttpMethod.POST)
76-
.uri(endpointUrl)
77-
.body(mapper.encode(outgoingRequest))
78-
.headers(HttpUtil.headers())
79-
.payload(outgoingRequest)
80-
.build()),
77+
HttpRequest.<BidRequest>builder()
78+
.method(HttpMethod.POST)
79+
.uri(endpointUrl)
80+
.body(mapper.encode(outgoingRequest))
81+
.headers(HttpUtil.headers())
82+
.payload(outgoingRequest)
83+
.build()),
8184
errors);
8285
}
8386

@@ -124,8 +127,9 @@ private ExtImpGumgum parseImpExt(Imp imp) {
124127

125128
private Imp modifyImp(Imp imp, ExtImpGumgum extImp) {
126129
final Imp.ImpBuilder impBuilder = imp.toBuilder();
127-
if (imp.getBanner() != null) {
128-
final Banner resolvedBanner = resolveBanner(imp.getBanner());
130+
final Banner banner = imp.getBanner();
131+
if (banner != null) {
132+
final Banner resolvedBanner = resolveBanner(banner, extImp);
129133
if (resolvedBanner != null) {
130134
impBuilder.banner(resolvedBanner);
131135
}
@@ -144,15 +148,35 @@ private Imp modifyImp(Imp imp, ExtImpGumgum extImp) {
144148
return impBuilder.build();
145149
}
146150

147-
private static Banner resolveBanner(Banner banner) {
151+
private Banner resolveBanner(Banner banner, ExtImpGumgum extImpGumgum) {
148152
final List<Format> format = banner.getFormat();
149153
if (banner.getH() == null && banner.getW() == null && CollectionUtils.isNotEmpty(format)) {
150154
final Format firstFormat = format.get(0);
151-
return banner.toBuilder().w(firstFormat.getW()).h(firstFormat.getH()).build();
155+
156+
final Long slot = extImpGumgum.getSlot();
157+
final ObjectNode bannerExt = slot != null && slot != 0L
158+
? mapper.mapper().valueToTree(resolveBannerExt(format, slot))
159+
: banner.getExt();
160+
161+
return banner.toBuilder()
162+
.w(firstFormat.getW())
163+
.h(firstFormat.getH())
164+
.ext(bannerExt)
165+
.build();
152166
}
153167
return null;
154168
}
155169

170+
private static ExtImpGumgumBanner resolveBannerExt(List<Format> formats, Long slot) {
171+
return formats.stream()
172+
.filter(format -> ObjectUtils.allNotNull(format.getW(), format.getH()))
173+
.max(Comparator.comparing((Format format) -> Math.max(format.getW(), format.getH()))
174+
.thenComparing(Format::getW)
175+
.thenComparing(Format::getH))
176+
.map(format -> ExtImpGumgumBanner.of(slot, format.getW(), format.getH()))
177+
.orElseGet(() -> ExtImpGumgumBanner.of(slot, 0, 0));
178+
}
179+
156180
private void validateVideoParams(Video video) {
157181
if (anyOfNull(
158182
video.getW(),

src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgum.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ public class ExtImpGumgum {
1717

1818
@JsonProperty("irisid")
1919
String irisId;
20+
21+
Long slot;
2022
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.prebid.server.proto.openrtb.ext.request.gumgum;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Value;
5+
6+
@Value
7+
@AllArgsConstructor(staticName = "of")
8+
public class ExtImpGumgumBanner {
9+
10+
Long slot;
11+
12+
Integer maxw;
13+
14+
Integer maxh;
15+
}

src/main/resources/static/bidder-params/gumgum.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"irisid": {
1717
"type": "string",
1818
"description": "A hashed IRIS.TV Content ID"
19+
},
20+
"slot": {
21+
"type": "integer",
22+
"description": "A slot id used to identify a slot placement mapped to a GumGum zone or publisher"
1923
}
2024
},
2125
"anyOf": [

src/test/java/org/prebid/server/bidder/gumgum/GumgumBidderTest.java

Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.prebid.server.bidder.model.Result;
2424
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
2525
import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgum;
26+
import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgumBanner;
2627
import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgumVideo;
2728

2829
import java.math.BigDecimal;
@@ -58,9 +59,8 @@ public void creationShouldFailOnInvalidEndpointUrl() {
5859
@Test
5960
public void makeHttpRequestsShouldReturnErrorsIfImpExtCouldNotBeParsed() {
6061
// given
61-
final BidRequest bidRequest = givenBidRequest(
62-
impBuilder -> impBuilder
63-
.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))));
62+
final BidRequest bidRequest = givenBidRequest(impBuilder ->
63+
impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))));
6464

6565
// when
6666
final Result<List<HttpRequest<BidRequest>>> result = gumgumBidder.makeHttpRequests(bidRequest);
@@ -101,7 +101,8 @@ public void makeHttpRequestsShouldReturnErrorIfVideoFieldsAreNotValid() {
101101
final BidRequest bidRequest = BidRequest.builder()
102102
.imp(singletonList(Imp.builder()
103103
.video(Video.builder().w(0).build())
104-
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone", BigInteger.TEN, "irisId"))))
104+
.ext(mapper.valueToTree(ExtPrebid.of(null,
105+
ExtImpGumgum.of("zone", BigInteger.TEN, "irisId", null))))
105106
.build()))
106107
.build();
107108

@@ -128,7 +129,8 @@ public void makeHttpRequestsShouldModifyVideoExtOfIrisIdIsPresent() {
128129
.placement(33)
129130
.linearity(233)
130131
.build())
131-
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone", BigInteger.TEN, "irisId"))))
132+
.ext(mapper.valueToTree(ExtPrebid.of(null,
133+
ExtImpGumgum.of("zone", BigInteger.TEN, "irisId", null))))
132134
.build()))
133135
.build();
134136

@@ -149,12 +151,11 @@ public void makeHttpRequestsShouldModifyVideoExtOfIrisIdIsPresent() {
149151
@Test
150152
public void makeHttpRequestsShouldNotChangeBannerWidthAndHeightIfPresent() {
151153
// given
152-
final BidRequest bidRequest = givenBidRequest(
153-
impBuilder -> impBuilder
154-
.banner(Banner.builder()
155-
.format(singletonList(Format.builder().w(300).h(450).build()))
156-
.w(600).h(900)
157-
.build()));
154+
final BidRequest bidRequest = givenBidRequest(impBuilder ->
155+
impBuilder.banner(Banner.builder()
156+
.format(singletonList(Format.builder().w(300).h(450).build()))
157+
.w(600).h(900)
158+
.build()));
158159

159160
// when
160161
final Result<List<HttpRequest<BidRequest>>> result = gumgumBidder.makeHttpRequests(bidRequest);
@@ -236,7 +237,7 @@ public void makeHttpRequestsShouldSetSiteIdFromLastValidImpExtZone() {
236237
givenImp(impBuilder -> impBuilder
237238
.banner(Banner.builder().build())
238239
.ext(mapper.valueToTree(ExtPrebid.of(null,
239-
ExtImpGumgum.of("ignored zone", BigInteger.TEN, "irisId"))))),
240+
ExtImpGumgum.of("ignored zone", BigInteger.TEN, "irisId", null))))),
240241
givenImp(identity())))
241242
.build();
242243

@@ -252,6 +253,69 @@ public void makeHttpRequestsShouldSetSiteIdFromLastValidImpExtZone() {
252253
.containsExactly("zone");
253254
}
254255

256+
@Test
257+
public void makeHttpRequestsShouldNotModifyBannerExtIfSlotIsZeroOrNull() {
258+
// given
259+
final BidRequest bidRequest = BidRequest.builder()
260+
.site(Site.builder().build())
261+
.imp(asList(
262+
givenImp(impBuilder -> impBuilder
263+
.id("123")
264+
.banner(Banner.builder()
265+
.format(singletonList(Format.builder().w(1).h(1).build()))
266+
.build())
267+
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("ignored zone",
268+
BigInteger.TEN, "irisId", 0L))))),
269+
givenImp(impBuilder -> impBuilder
270+
.id("345")
271+
.banner(Banner.builder()
272+
.format(singletonList(Format.builder().w(1).h(1).build()))
273+
.build())
274+
.ext(mapper.valueToTree(ExtPrebid.of(null,
275+
ExtImpGumgum.of("ignored zone", BigInteger.TEN, "irisId", null))))
276+
)))
277+
.build();
278+
279+
// when
280+
final Result<List<HttpRequest<BidRequest>>> result = gumgumBidder.makeHttpRequests(bidRequest);
281+
282+
// then
283+
assertThat(result.getErrors()).isEmpty();
284+
assertThat(result.getValue())
285+
.extracting(HttpRequest::getPayload)
286+
.flatExtracting(BidRequest::getImp)
287+
.extracting(Imp::getBanner)
288+
.extracting(Banner::getExt)
289+
.containsExactly(null, null);
290+
}
291+
292+
@Test
293+
public void makeHttpRequestsShouldSetBannerExtWithBiggestBannerFormatIfSlotIsNotZero() {
294+
// given
295+
final BidRequest bidRequest = givenBidRequest(impBuilder -> impBuilder
296+
.id("123")
297+
.banner(Banner.builder()
298+
.format(asList(
299+
Format.builder().w(120).h(80).build(),
300+
Format.builder().w(120).h(100).build(),
301+
Format.builder().w(100).h(100).build()))
302+
.build())
303+
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("ignored zone",
304+
BigInteger.TEN, "irisId", 42L)))));
305+
306+
// when
307+
final Result<List<HttpRequest<BidRequest>>> result = gumgumBidder.makeHttpRequests(bidRequest);
308+
309+
// then
310+
assertThat(result.getErrors()).isEmpty();
311+
assertThat(result.getValue())
312+
.extracting(HttpRequest::getPayload)
313+
.flatExtracting(BidRequest::getImp)
314+
.extracting(Imp::getBanner)
315+
.extracting(Banner::getExt)
316+
.containsExactly(mapper.valueToTree(ExtImpGumgumBanner.of(42L, 120, 100)));
317+
}
318+
255319
@Test
256320
public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() {
257321
// given
@@ -370,7 +434,7 @@ private static BidRequest givenBidRequest(
370434
Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer) {
371435

372436
return bidRequestCustomizer.apply(BidRequest.builder()
373-
.imp(singletonList(givenImp(impCustomizer))))
437+
.imp(singletonList(givenImp(impCustomizer))))
374438
.build();
375439
}
376440

@@ -380,9 +444,10 @@ private static BidRequest givenBidRequest(Function<Imp.ImpBuilder, Imp.ImpBuilde
380444

381445
private static Imp givenImp(Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer) {
382446
return impCustomizer.apply(Imp.builder()
383-
.id("123")
384-
.banner(Banner.builder().id("banner_id").build())
385-
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone", BigInteger.TEN, "irisId")))))
447+
.id("123")
448+
.banner(Banner.builder().id("banner_id").build())
449+
.ext(mapper.valueToTree(ExtPrebid.of(null,
450+
ExtImpGumgum.of("zone", BigInteger.TEN, "irisId", 1L)))))
386451
.build();
387452
}
388453

0 commit comments

Comments
 (0)