Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package org.prebid.server.bidder.zeta_global_ssp;

import com.fasterxml.jackson.core.type.TypeReference;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import org.prebid.server.bidder.Bidder;
import org.prebid.server.bidder.model.BidderBid;
import org.prebid.server.bidder.model.BidderCall;
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.bidder.model.HttpRequest;
import org.prebid.server.bidder.model.Result;
import org.prebid.server.exception.PreBidException;
import org.prebid.server.json.DecodeException;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
import org.prebid.server.proto.openrtb.ext.request.zeta_global_ssp.ExtImpZetaGlobalSSP;
import org.prebid.server.proto.openrtb.ext.response.BidType;
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class ZetaGlobalSspBidder implements Bidder<BidRequest> {

private static final TypeReference<ExtPrebid<?, ExtImpZetaGlobalSSP>> ZETA_GLOBAL_EXT_TYPE_REFERENCE =
new TypeReference<>() {
};

private static final TypeReference<ExtPrebid<ExtBidPrebid, ?>> EXT_BID_TYPE_REFERENCE =
new TypeReference<>() {
};
private static final String SID_MACRO = "{{AccountID}}";

private final String endpointUrl;
private final JacksonMapper mapper;

public ZetaGlobalSspBidder(String endpointUrl, JacksonMapper mapper) {
this.endpointUrl = HttpUtil.validateUrl(endpointUrl);
this.mapper = Objects.requireNonNull(mapper);
}

@Override
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
final Imp firstImp = request.getImp().getFirst();
final ExtImpZetaGlobalSSP extImp;

try {
extImp = parseImpExt(firstImp);
} catch (PreBidException e) {
return Result.withError(BidderError.badInput(e.getMessage()));
}

final HttpRequest<BidRequest> httpRequest = BidderUtil.defaultRequest(
removeImpsExt(request),
resolveEndpoint(extImp),
mapper);

return Result.withValues(Collections.singletonList(httpRequest));
}

private ExtImpZetaGlobalSSP parseImpExt(Imp imp) {
try {
return mapper.mapper().convertValue(imp.getExt(), ZETA_GLOBAL_EXT_TYPE_REFERENCE).getBidder();
} catch (IllegalArgumentException e) {
throw new PreBidException("Missing bidder ext in impression with id: " + imp.getId());
}
}

private String resolveEndpoint(ExtImpZetaGlobalSSP extImpZetaGlobalSSP) {
return endpointUrl
.replace(SID_MACRO, Objects.toString(extImpZetaGlobalSSP.getSid(), "0"));
}

private BidRequest removeImpsExt(BidRequest request) {
final List<Imp> imps = new ArrayList<>(request.getImp());
final Imp firstImp = imps.getFirst().toBuilder().ext(null).build();
imps.set(0, firstImp);

return request.toBuilder()
.imp(imps)
.build();
}

@Override
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
try {
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
final List<BidderError> errors = new ArrayList<>();
return Result.of(extractBids(bidResponse, errors), errors);
} catch (DecodeException | PreBidException e) {
return Result.withError(BidderError.badServerResponse(e.getMessage()));
}
}

private List<BidderBid> extractBids(BidResponse bidResponse, List<BidderError> errors) {
if (bidResponse == null || bidResponse.getSeatbid() == null) {
return Collections.emptyList();
}
return bidsFromResponse(bidResponse, errors);
}

private List<BidderBid> bidsFromResponse(BidResponse bidResponse, List<BidderError> errors) {
return bidResponse.getSeatbid().stream()
.filter(Objects::nonNull)
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.map(bid -> makeBid(bid, bidResponse.getCur(), errors))
.filter(Objects::nonNull)
.toList();
}

private BidderBid makeBid(Bid bid, String currency, List<BidderError> errors) {
final BidType mediaType = getMediaType(bid, errors);
return mediaType == null ? null : BidderBid.of(bid, mediaType, currency);
}

private BidType getMediaType(Bid bid, List<BidderError> errors) {
try {
return Optional.ofNullable(bid.getExt())
.map(ext -> mapper.mapper().convertValue(ext, EXT_BID_TYPE_REFERENCE))
.map(ExtPrebid::getPrebid)
.map(ExtBidPrebid::getType)
.orElseThrow(IllegalArgumentException::new);
} catch (IllegalArgumentException e) {
errors.add(BidderError.badServerResponse(
"Failed to parse impression \"%s\" mediatype".formatted(bid.getImpid())));
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.prebid.server.proto.openrtb.ext.request.zeta_global_ssp;

import lombok.Value;

@Value(staticConstructor = "of")
public class ExtImpZetaGlobalSSP {

Integer sid;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.prebid.server.spring.config.bidder;

import org.prebid.server.bidder.BidderDeps;
import org.prebid.server.bidder.zeta_global_ssp.ZetaGlobalSspBidder;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties;
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler;
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator;
import org.prebid.server.spring.env.YamlPropertySourceFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import jakarta.validation.constraints.NotBlank;

@Configuration
@PropertySource(value = "classpath:/bidder-config/zeta_global_ssp.yaml", factory = YamlPropertySourceFactory.class)
public class ZetaGlobalSspConfiguration {

private static final String BIDDER_NAME = "zeta_global_ssp";

@Bean("zetaglobalsspConfigurationProperties")
@ConfigurationProperties("adapters.zetaglobalssp")
BidderConfigurationProperties configurationProperties() {
return new BidderConfigurationProperties();
}

@Bean
BidderDeps zetaGlobalSspBidderDeps(@Qualifier("zetaglobalsspConfigurationProperties")
BidderConfigurationProperties zetaGlobalSspConfigurationProperties,
@NotBlank @Value("${external-url}") String externalUrl,
JacksonMapper mapper) {

return BidderDepsAssembler.forBidder(BIDDER_NAME)
.withConfig(zetaGlobalSspConfigurationProperties)
.usersyncerCreator(UsersyncerCreator.create(externalUrl))
.bidderCreator(config -> new ZetaGlobalSspBidder(config.getEndpoint(), mapper))
.assemble();
}
}
21 changes: 0 additions & 21 deletions src/main/resources/bidder-config/generic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,6 @@ adapters:
- video
supported-vendors:
vendor-id: 0
zeta_global_ssp:
enabled: false
endpoint: https://ssp.disqus.com/bid/prebid-server?sid=GET_SID_FROM_ZETA
endpoint-compression: gzip
meta-info:
maintainer-email: [email protected]
app-media-types:
- banner
- video
site-media-types:
- banner
- video
supported-vendors:
vendor-id: 833
usersync:
enabled: true
cookie-family-name: zeta_global_ssp
redirect:
url: https://ssp.disqus.com/redirectuser?sid=GET_SID_FROM_ZETA&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&r={{redirect_url}}
uid-macro: 'BUYERUID'
support-cors: false
blue:
enabled: false
endpoint: https://prebid-us-east-1.getblue.io/?src=prebid
Expand Down
23 changes: 23 additions & 0 deletions src/main/resources/bidder-config/zeta_global_ssp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
adapters:
zeta_global_ssp:
endpoint: https://ssp.disqus.com/bid/prebid-server?sid={{AccountID}}
endpoint-compression: gzip
ortb-version: "2.6"
modifying-vast-xml-allowed: true
meta-info:
maintainer-email: [email protected]
app-media-types:
- banner
- video
- audio
site-media-types:
- banner
- video
- audio
vendor-id: 833
usersync:
cookie-family-name: zeta_global_ssp
redirect:
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}}
support-cors: false
uid-macro: 'BUYERUID'
13 changes: 8 additions & 5 deletions src/main/resources/static/bidder-params/zeta_global_ssp.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Zeta Global SSP Adapter Params",
"description": "A schema which validates params accepted by the Zeta SSP adapter",
"type": "object",

"properties": {},
"description": "A schema which validates params accepted by the Zeta Global SSP adapter",

"required": []
"type": "object",
"properties": {
"sid": {
"type": "integer",
"description": "An ID which identifies the publisher"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ LIMIT 1
"adapters.generic.aliases.nativo.meta-info.site-media-types" : "",
"adapters.generic.aliases.infytv.meta-info.app-media-types" : "",
"adapters.generic.aliases.infytv.meta-info.site-media-types" : "",
"adapters.generic.aliases.zeta-global-ssp.meta-info.app-media-types" : "",
"adapters.generic.aliases.zeta-global-ssp.meta-info.site-media-types": "",
"adapters.generic.aliases.ccx.meta-info.app-media-types" : "",
"adapters.generic.aliases.ccx.meta-info.site-media-types" : "",
"adapters.generic.aliases.adrino.meta-info.app-media-types" : "",
Expand Down
Loading
Loading