Skip to content

Commit 794c62f

Browse files
ZetaGlobalSSP Adapter: Add sid parameter and audio support (prebid#4055)
1 parent 4a6fb6c commit 794c62f

File tree

12 files changed

+461
-44
lines changed

12 files changed

+461
-44
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package org.prebid.server.bidder.zeta_global_ssp;
2+
3+
import com.fasterxml.jackson.core.type.TypeReference;
4+
import com.iab.openrtb.request.BidRequest;
5+
import com.iab.openrtb.request.Imp;
6+
import com.iab.openrtb.response.Bid;
7+
import com.iab.openrtb.response.BidResponse;
8+
import com.iab.openrtb.response.SeatBid;
9+
import org.prebid.server.bidder.Bidder;
10+
import org.prebid.server.bidder.model.BidderBid;
11+
import org.prebid.server.bidder.model.BidderCall;
12+
import org.prebid.server.bidder.model.BidderError;
13+
import org.prebid.server.bidder.model.HttpRequest;
14+
import org.prebid.server.bidder.model.Result;
15+
import org.prebid.server.exception.PreBidException;
16+
import org.prebid.server.json.DecodeException;
17+
import org.prebid.server.json.JacksonMapper;
18+
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
19+
import org.prebid.server.proto.openrtb.ext.request.zeta_global_ssp.ExtImpZetaGlobalSSP;
20+
import org.prebid.server.proto.openrtb.ext.response.BidType;
21+
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
22+
import org.prebid.server.util.BidderUtil;
23+
import org.prebid.server.util.HttpUtil;
24+
25+
import java.util.ArrayList;
26+
import java.util.Collection;
27+
import java.util.Collections;
28+
import java.util.List;
29+
import java.util.Objects;
30+
import java.util.Optional;
31+
32+
public class ZetaGlobalSspBidder implements Bidder<BidRequest> {
33+
34+
private static final TypeReference<ExtPrebid<?, ExtImpZetaGlobalSSP>> ZETA_GLOBAL_EXT_TYPE_REFERENCE =
35+
new TypeReference<>() {
36+
};
37+
38+
private static final TypeReference<ExtPrebid<ExtBidPrebid, ?>> EXT_BID_TYPE_REFERENCE =
39+
new TypeReference<>() {
40+
};
41+
private static final String SID_MACRO = "{{AccountID}}";
42+
43+
private final String endpointUrl;
44+
private final JacksonMapper mapper;
45+
46+
public ZetaGlobalSspBidder(String endpointUrl, JacksonMapper mapper) {
47+
this.endpointUrl = HttpUtil.validateUrl(endpointUrl);
48+
this.mapper = Objects.requireNonNull(mapper);
49+
}
50+
51+
@Override
52+
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
53+
final Imp firstImp = request.getImp().getFirst();
54+
final ExtImpZetaGlobalSSP extImp;
55+
56+
try {
57+
extImp = parseImpExt(firstImp);
58+
} catch (PreBidException e) {
59+
return Result.withError(BidderError.badInput(e.getMessage()));
60+
}
61+
62+
final HttpRequest<BidRequest> httpRequest = BidderUtil.defaultRequest(
63+
removeImpsExt(request),
64+
resolveEndpoint(extImp),
65+
mapper);
66+
67+
return Result.withValues(Collections.singletonList(httpRequest));
68+
}
69+
70+
private ExtImpZetaGlobalSSP parseImpExt(Imp imp) {
71+
try {
72+
return mapper.mapper().convertValue(imp.getExt(), ZETA_GLOBAL_EXT_TYPE_REFERENCE).getBidder();
73+
} catch (IllegalArgumentException e) {
74+
throw new PreBidException("Missing bidder ext in impression with id: " + imp.getId());
75+
}
76+
}
77+
78+
private String resolveEndpoint(ExtImpZetaGlobalSSP extImpZetaGlobalSSP) {
79+
return endpointUrl
80+
.replace(SID_MACRO, Objects.toString(extImpZetaGlobalSSP.getSid(), "0"));
81+
}
82+
83+
private BidRequest removeImpsExt(BidRequest request) {
84+
final List<Imp> imps = new ArrayList<>(request.getImp());
85+
final Imp firstImp = imps.getFirst().toBuilder().ext(null).build();
86+
imps.set(0, firstImp);
87+
88+
return request.toBuilder()
89+
.imp(imps)
90+
.build();
91+
}
92+
93+
@Override
94+
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
95+
try {
96+
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
97+
final List<BidderError> errors = new ArrayList<>();
98+
return Result.of(extractBids(bidResponse, errors), errors);
99+
} catch (DecodeException | PreBidException e) {
100+
return Result.withError(BidderError.badServerResponse(e.getMessage()));
101+
}
102+
}
103+
104+
private List<BidderBid> extractBids(BidResponse bidResponse, List<BidderError> errors) {
105+
if (bidResponse == null || bidResponse.getSeatbid() == null) {
106+
return Collections.emptyList();
107+
}
108+
return bidsFromResponse(bidResponse, errors);
109+
}
110+
111+
private List<BidderBid> bidsFromResponse(BidResponse bidResponse, List<BidderError> errors) {
112+
return bidResponse.getSeatbid().stream()
113+
.filter(Objects::nonNull)
114+
.map(SeatBid::getBid)
115+
.filter(Objects::nonNull)
116+
.flatMap(Collection::stream)
117+
.filter(Objects::nonNull)
118+
.map(bid -> makeBid(bid, bidResponse.getCur(), errors))
119+
.filter(Objects::nonNull)
120+
.toList();
121+
}
122+
123+
private BidderBid makeBid(Bid bid, String currency, List<BidderError> errors) {
124+
final BidType mediaType = getMediaType(bid, errors);
125+
return mediaType == null ? null : BidderBid.of(bid, mediaType, currency);
126+
}
127+
128+
private BidType getMediaType(Bid bid, List<BidderError> errors) {
129+
try {
130+
return Optional.ofNullable(bid.getExt())
131+
.map(ext -> mapper.mapper().convertValue(ext, EXT_BID_TYPE_REFERENCE))
132+
.map(ExtPrebid::getPrebid)
133+
.map(ExtBidPrebid::getType)
134+
.orElseThrow(IllegalArgumentException::new);
135+
} catch (IllegalArgumentException e) {
136+
errors.add(BidderError.badServerResponse(
137+
"Failed to parse impression \"%s\" mediatype".formatted(bid.getImpid())));
138+
return null;
139+
}
140+
}
141+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.prebid.server.proto.openrtb.ext.request.zeta_global_ssp;
2+
3+
import lombok.Value;
4+
5+
@Value(staticConstructor = "of")
6+
public class ExtImpZetaGlobalSSP {
7+
8+
Integer sid;
9+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.prebid.server.spring.config.bidder;
2+
3+
import org.prebid.server.bidder.BidderDeps;
4+
import org.prebid.server.bidder.zeta_global_ssp.ZetaGlobalSspBidder;
5+
import org.prebid.server.json.JacksonMapper;
6+
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties;
7+
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler;
8+
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator;
9+
import org.prebid.server.spring.env.YamlPropertySourceFactory;
10+
import org.springframework.beans.factory.annotation.Qualifier;
11+
import org.springframework.beans.factory.annotation.Value;
12+
import org.springframework.boot.context.properties.ConfigurationProperties;
13+
import org.springframework.context.annotation.Bean;
14+
import org.springframework.context.annotation.Configuration;
15+
import org.springframework.context.annotation.PropertySource;
16+
17+
import jakarta.validation.constraints.NotBlank;
18+
19+
@Configuration
20+
@PropertySource(value = "classpath:/bidder-config/zeta_global_ssp.yaml", factory = YamlPropertySourceFactory.class)
21+
public class ZetaGlobalSspConfiguration {
22+
23+
private static final String BIDDER_NAME = "zeta_global_ssp";
24+
25+
@Bean("zetaglobalsspConfigurationProperties")
26+
@ConfigurationProperties("adapters.zetaglobalssp")
27+
BidderConfigurationProperties configurationProperties() {
28+
return new BidderConfigurationProperties();
29+
}
30+
31+
@Bean
32+
BidderDeps zetaGlobalSspBidderDeps(@Qualifier("zetaglobalsspConfigurationProperties")
33+
BidderConfigurationProperties zetaGlobalSspConfigurationProperties,
34+
@NotBlank @Value("${external-url}") String externalUrl,
35+
JacksonMapper mapper) {
36+
37+
return BidderDepsAssembler.forBidder(BIDDER_NAME)
38+
.withConfig(zetaGlobalSspConfigurationProperties)
39+
.usersyncerCreator(UsersyncerCreator.create(externalUrl))
40+
.bidderCreator(config -> new ZetaGlobalSspBidder(config.getEndpoint(), mapper))
41+
.assemble();
42+
}
43+
}

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

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,6 @@ adapters:
4141
- video
4242
supported-vendors:
4343
vendor-id: 0
44-
zeta_global_ssp:
45-
enabled: false
46-
endpoint: https://ssp.disqus.com/bid/prebid-server?sid=GET_SID_FROM_ZETA
47-
endpoint-compression: gzip
48-
meta-info:
49-
maintainer-email: [email protected]
50-
app-media-types:
51-
- banner
52-
- video
53-
site-media-types:
54-
- banner
55-
- video
56-
supported-vendors:
57-
vendor-id: 833
58-
usersync:
59-
enabled: true
60-
cookie-family-name: zeta_global_ssp
61-
redirect:
62-
url: https://ssp.disqus.com/redirectuser?sid=GET_SID_FROM_ZETA&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&r={{redirect_url}}
63-
uid-macro: 'BUYERUID'
64-
support-cors: false
6544
blue:
6645
enabled: false
6746
endpoint: https://prebid-us-east-1.getblue.io/?src=prebid
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
adapters:
2+
zeta_global_ssp:
3+
endpoint: https://ssp.disqus.com/bid/prebid-server?sid={{AccountID}}
4+
endpoint-compression: gzip
5+
ortb-version: "2.6"
6+
modifying-vast-xml-allowed: true
7+
meta-info:
8+
maintainer-email: [email protected]
9+
app-media-types:
10+
- banner
11+
- video
12+
- audio
13+
site-media-types:
14+
- banner
15+
- video
16+
- audio
17+
vendor-id: 833
18+
usersync:
19+
cookie-family-name: zeta_global_ssp
20+
redirect:
21+
url: https://ssp.disqus.com/redirectuser?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&gpp={{gpp}}&gpp_sid={{gpp_sid}}&r={{redirect_url}}
22+
support-cors: false
23+
uid-macro: 'BUYERUID'
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
{
22
"$schema": "http://json-schema.org/draft-04/schema#",
33
"title": "Zeta Global SSP Adapter Params",
4-
"description": "A schema which validates params accepted by the Zeta SSP adapter",
5-
"type": "object",
6-
7-
"properties": {},
4+
"description": "A schema which validates params accepted by the Zeta Global SSP adapter",
85

9-
"required": []
6+
"type": "object",
7+
"properties": {
8+
"sid": {
9+
"type": "integer",
10+
"description": "An ID which identifies the publisher"
11+
}
12+
}
1013
}

src/test/groovy/org/prebid/server/functional/testcontainers/PbsConfig.groovy

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@ LIMIT 1
129129
"adapters.generic.aliases.nativo.meta-info.site-media-types" : "",
130130
"adapters.generic.aliases.infytv.meta-info.app-media-types" : "",
131131
"adapters.generic.aliases.infytv.meta-info.site-media-types" : "",
132-
"adapters.generic.aliases.zeta-global-ssp.meta-info.app-media-types" : "",
133-
"adapters.generic.aliases.zeta-global-ssp.meta-info.site-media-types": "",
134132
"adapters.generic.aliases.ccx.meta-info.app-media-types" : "",
135133
"adapters.generic.aliases.ccx.meta-info.site-media-types" : "",
136134
"adapters.generic.aliases.adrino.meta-info.app-media-types" : "",

0 commit comments

Comments
 (0)