Skip to content

Commit e3216fb

Browse files
Equativ: SmartAdserver alias with update to use mtype (#3678)
1 parent b5d5380 commit e3216fb

File tree

11 files changed

+272
-41
lines changed

11 files changed

+272
-41
lines changed

src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,13 @@ private static Publisher modifyPublisher(Publisher publisher, Integer networkId)
112112
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
113113
try {
114114
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
115-
return extractBids(httpCall.getRequest().getPayload(), bidResponse);
115+
return extractBids(bidResponse);
116116
} catch (DecodeException | PreBidException e) {
117117
return Result.withError(BidderError.badServerResponse(e.getMessage()));
118118
}
119119
}
120120

121-
private Result<List<BidderBid>> extractBids(BidRequest bidRequest, BidResponse bidResponse) {
121+
private Result<List<BidderBid>> extractBids(BidResponse bidResponse) {
122122
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
123123
return Result.empty();
124124
}
@@ -128,19 +128,18 @@ private Result<List<BidderBid>> extractBids(BidRequest bidRequest, BidResponse b
128128
.map(SeatBid::getBid)
129129
.filter(Objects::nonNull)
130130
.flatMap(Collection::stream)
131-
.map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur()))
131+
.map(bid -> BidderBid.of(bid, getBidTypeFromMarkupType(bid.getMtype()), bidResponse.getCur()))
132132
.toList();
133133
return Result.of(bidderBids, errors);
134134
}
135135

136-
private static BidType getBidType(String impId, List<Imp> imps) {
137-
for (Imp imp : imps) {
138-
if (imp.getId().equals(impId)) {
139-
return imp.getVideo() != null
140-
? BidType.video
141-
: (imp.getXNative() != null ? BidType.xNative : BidType.banner);
142-
}
143-
}
144-
return BidType.banner;
136+
private static BidType getBidTypeFromMarkupType(Integer markupType) {
137+
return switch (markupType) {
138+
case 1 -> BidType.banner;
139+
case 2 -> BidType.video;
140+
case 3 -> BidType.audio;
141+
case 4 -> BidType.xNative;
142+
case null, default -> BidType.banner;
143+
};
145144
}
146145
}

src/main/resources/bidder-config/smartadserver.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
adapters:
22
smartadserver:
33
endpoint: https://ssb-global.smartadserver.com
4+
endpoint-compression: gzip
5+
aliases:
6+
equativ:
7+
enabled: false
48
meta-info:
59
maintainer-email: [email protected]
610
app-media-types:
711
- banner
812
- video
913
- native
14+
- audio
1015
site-media-types:
1116
- banner
1217
- video
1318
- native
19+
- audio
1420
supported-vendors:
1521
vendor-id: 45
1622
usersync:

src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.iab.openrtb.request.Banner;
55
import com.iab.openrtb.request.BidRequest;
66
import com.iab.openrtb.request.Imp;
7-
import com.iab.openrtb.request.Native;
87
import com.iab.openrtb.request.Publisher;
98
import com.iab.openrtb.request.Site;
109
import com.iab.openrtb.request.Video;
@@ -27,8 +26,10 @@
2726
import java.util.function.Function;
2827

2928
import static java.util.Collections.singletonList;
29+
import static java.util.function.UnaryOperator.identity;
3030
import static org.assertj.core.api.Assertions.assertThat;
3131
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
32+
import static org.prebid.server.proto.openrtb.ext.response.BidType.audio;
3233
import static org.prebid.server.proto.openrtb.ext.response.BidType.banner;
3334
import static org.prebid.server.proto.openrtb.ext.response.BidType.video;
3435
import static org.prebid.server.proto.openrtb.ext.response.BidType.xNative;
@@ -66,7 +67,7 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() {
6667
public void makeHttpRequestsShouldCreateCorrectURL() {
6768
// given
6869
final BidRequest bidRequest = BidRequest.builder()
69-
.imp(singletonList(givenImp(Function.identity())))
70+
.imp(singletonList(givenImp(identity())))
7071
.build();
7172

7273
// when
@@ -83,7 +84,7 @@ public void makeHttpRequestsShouldCreateCorrectURL() {
8384
public void makeHttpRequestsShouldUpdateSiteObjectIfPresent() {
8485
// given
8586
final BidRequest bidRequest = BidRequest.builder()
86-
.imp(singletonList(givenImp(Function.identity())))
87+
.imp(singletonList(givenImp(identity())))
8788
.site(Site.builder()
8889
.domain("www.foo.com")
8990
.publisher(Publisher.builder().domain("foo.com").build())
@@ -110,7 +111,7 @@ public void makeHttpRequestsShouldUpdateSiteObjectIfPresent() {
110111
public void makeHttpRequestsShouldCreateRequestForEveryValidImp() {
111112
// given
112113
final BidRequest bidRequest = BidRequest.builder()
113-
.imp(Arrays.asList(givenImp(Function.identity()),
114+
.imp(Arrays.asList(givenImp(identity()),
114115
givenImp(impBuilder -> impBuilder.id("456"))
115116
))
116117
.build();
@@ -196,33 +197,46 @@ public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws Jso
196197
}
197198

198199
@Test
199-
public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException {
200+
public void makeBidsShouldReturnBannerBidIfMarkupTypeIsBanner() throws JsonProcessingException {
200201
// given
201202
final BidderCall<BidRequest> httpCall = givenHttpCall(
202-
BidRequest.builder()
203-
.imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build()))
204-
.build(),
203+
BidRequest.builder().build(),
205204
mapper.writeValueAsString(
206-
givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
205+
givenBidResponse(bidBuilder -> bidBuilder.mtype(1))));
207206

208207
// when
209208
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);
210209

211210
// then
212211
assertThat(result.getErrors()).isEmpty();
213212
assertThat(result.getValue())
214-
.containsOnly(BidderBid.of(Bid.builder().impid("123").build(), banner, "EUR"));
213+
.containsOnly(BidderBid.of(Bid.builder().mtype(1).build(), banner, "EUR"));
215214
}
216215

217216
@Test
218-
public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingException {
217+
public void makeBidsShouldReturnAudioBidIfMarkupTypeIsAudio() throws JsonProcessingException {
219218
// given
220219
final BidderCall<BidRequest> httpCall = givenHttpCall(
221-
BidRequest.builder()
222-
.imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build()))
223-
.build(),
220+
BidRequest.builder().build(),
224221
mapper.writeValueAsString(
225-
givenBidResponse(Function.identity())));
222+
givenBidResponse(bidBuilder -> bidBuilder.mtype(3))));
223+
224+
// when
225+
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);
226+
227+
// then
228+
assertThat(result.getErrors()).isEmpty();
229+
assertThat(result.getValue())
230+
.containsOnly(BidderBid.of(Bid.builder().mtype(3).build(), audio, "EUR"));
231+
}
232+
233+
@Test
234+
public void makeBidsShouldReturnBannerBidIfMarkupTypeIsNull() throws JsonProcessingException {
235+
// given
236+
final BidderCall<BidRequest> httpCall = givenHttpCall(
237+
BidRequest.builder().build(),
238+
mapper.writeValueAsString(
239+
givenBidResponse(identity())));
226240

227241
// when
228242
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);
@@ -234,41 +248,54 @@ public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingExcept
234248
}
235249

236250
@Test
237-
public void makeBidsShouldReturnVideoBidIfVideoIsPresent() throws JsonProcessingException {
251+
public void makeBidsShouldReturnBannerBidIfMarkupTypeOutOfBounds() throws JsonProcessingException {
252+
// given
253+
final BidderCall<BidRequest> httpCall = givenHttpCall(
254+
BidRequest.builder().build(),
255+
mapper.writeValueAsString(
256+
givenBidResponse(bidBuilder -> bidBuilder.mtype(5))));
257+
258+
// when
259+
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);
260+
261+
// then
262+
assertThat(result.getErrors()).isEmpty();
263+
assertThat(result.getValue())
264+
.containsOnly(BidderBid.of(Bid.builder().mtype(5).build(), banner, "EUR"));
265+
}
266+
267+
@Test
268+
public void makeBidsShouldReturnVideoBidIfMarkupTypeIsVideo() throws JsonProcessingException {
238269
// given
239270
final BidderCall<BidRequest> httpCall = givenHttpCall(
240-
BidRequest.builder()
241-
.imp(singletonList(Imp.builder().id("123").video(Video.builder().build()).build()))
242-
.build(),
271+
BidRequest.builder().build(),
243272
mapper.writeValueAsString(
244-
givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
273+
givenBidResponse(bidBuilder -> bidBuilder.mtype(2))));
245274

246275
// when
247276
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);
248277

249278
// then
250279
assertThat(result.getErrors()).isEmpty();
251280
assertThat(result.getValue())
252-
.containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, "EUR"));
281+
.containsOnly(BidderBid.of(Bid.builder().mtype(2).build(), video, "EUR"));
253282
}
254283

255284
@Test
256-
public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessingException {
285+
public void makeBidsShouldReturnNativeBidIfMarkupTypeIsNative() throws JsonProcessingException {
257286
// given
258287
final BidderCall<BidRequest> httpCall = givenHttpCall(
259-
BidRequest.builder()
260-
.imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build()))
261-
.build(),
288+
BidRequest.builder().build(),
262289
mapper.writeValueAsString(
263-
givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
290+
givenBidResponse(bidBuilder -> bidBuilder.mtype(4))));
264291

265292
// when
266293
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);
267294

268295
// then
269296
assertThat(result.getErrors()).isEmpty();
270297
assertThat(result.getValue())
271-
.containsOnly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "EUR"));
298+
.containsOnly(BidderBid.of(Bid.builder().mtype(4).build(), xNative, "EUR"));
272299
}
273300

274301
private static Imp givenImp(Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.prebid.server.it;
2+
3+
import io.restassured.response.Response;
4+
import org.json.JSONException;
5+
import org.junit.jupiter.api.Test;
6+
import org.prebid.server.model.Endpoint;
7+
8+
import java.io.IOException;
9+
10+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
11+
import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
12+
import static com.github.tomakehurst.wiremock.client.WireMock.post;
13+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
14+
import static java.util.Collections.singletonList;
15+
16+
public class EquativTest extends IntegrationTest {
17+
18+
@Test
19+
public void openrtb2AuctionShouldRespondWithBidsFromEquativ() throws IOException, JSONException {
20+
// given
21+
WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/smartadserver-exchange/api/bid"))
22+
.withRequestBody(
23+
equalToJson(jsonFrom("openrtb2/equativ/test-equativ-bid-request.json")))
24+
.willReturn(aResponse()
25+
.withBody(jsonFrom("openrtb2/equativ/test-equativ-bid-response.json"))));
26+
27+
// when
28+
final Response response = responseFor(
29+
"openrtb2/equativ/test-auction-equativ-request.json",
30+
Endpoint.openrtb2_auction);
31+
32+
// then
33+
assertJsonEquals("openrtb2/equativ/test-auction-equativ-response.json", response,
34+
singletonList("equativ"));
35+
}
36+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"id": "request_id",
3+
"imp": [
4+
{
5+
"id": "imp_id",
6+
"banner": {
7+
"w": 300,
8+
"h": 250
9+
},
10+
"ext": {
11+
"prebid": {
12+
"bidder": {
13+
"equativ": {
14+
"siteId": 1,
15+
"pageId": 2,
16+
"formatId": 3,
17+
"networkId": 73
18+
}
19+
}
20+
}
21+
}
22+
}
23+
],
24+
"tmax": 5000,
25+
"regs": {
26+
"ext": {
27+
"gdpr": 0
28+
}
29+
}
30+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"id": "request_id",
3+
"seatbid": [
4+
{
5+
"bid": [
6+
{
7+
"id": "bid_id",
8+
"impid": "imp_id",
9+
"exp": 300,
10+
"price": 0.5,
11+
"adm": "some-test-ad",
12+
"adid": "adid",
13+
"adomain": [
14+
"advertsite.com"
15+
],
16+
"cid": "cid",
17+
"crid": "crid",
18+
"w": 1024,
19+
"h": 576,
20+
"ext": {
21+
"prebid": {
22+
"type": "banner",
23+
"meta": {
24+
"adaptercode": "equativ"
25+
}
26+
},
27+
"origbidcpm": 0.5
28+
},
29+
"mtype": 1
30+
}
31+
],
32+
"seat": "equativ",
33+
"group": 0
34+
}
35+
],
36+
"cur": "USD",
37+
"ext": {
38+
"responsetimemillis": {
39+
"equativ": "{{ equativ.response_time_ms }}"
40+
},
41+
"prebid": {
42+
"auctiontimestamp": 0
43+
},
44+
"tmaxrequest": 5000
45+
}
46+
}

0 commit comments

Comments
 (0)