Skip to content

Commit

Permalink
Loopme: Add Bidder (prebid#3394)
Browse files Browse the repository at this point in the history
  • Loading branch information
ambalashov authored and sergseven committed Dec 23, 2024
1 parent 3ac30bc commit db72a00
Show file tree
Hide file tree
Showing 11 changed files with 442 additions and 36 deletions.
95 changes: 95 additions & 0 deletions src/main/java/org/prebid/server/bidder/loopme/LoopmeBidder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.prebid.server.bidder.loopme;

import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import io.vertx.core.http.HttpMethod;
import org.apache.commons.collections4.CollectionUtils;
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.response.BidType;
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class LoopmeBidder implements Bidder<BidRequest> {

private final String endpointUrl;

private final JacksonMapper mapper;

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

@Override
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {

return Result.withValue(HttpRequest.<BidRequest>builder()
.method(HttpMethod.POST)
.uri(endpointUrl)
.headers(HttpUtil.headers())
.impIds(BidderUtil.impIds(request))
.body(mapper.encodeToBytes(request))
.payload(request)
.build());
}

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

private static List<BidderBid> extractBids(BidRequest bidRequest, BidResponse bidResponse) {
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
return Collections.emptyList();
}
return bidsFromResponse(bidRequest, bidResponse);
}

private static List<BidderBid> bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) {
return bidResponse.getSeatbid().stream()
.filter(Objects::nonNull)
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur()))
.collect(Collectors.toList());
}

private static BidType getBidType(String impId, List<Imp> imps) {
for (Imp imp : imps) {
if (imp.getId().equals(impId)) {
if (imp.getBanner() != null) {
return BidType.banner;
} else if (imp.getVideo() != null) {
return BidType.video;
} else if (imp.getAudio() != null) {
return BidType.audio;
} else if (imp.getXNative() != null) {
return BidType.xNative;
}
}
}
return BidType.banner;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package org.prebid.server.proto.openrtb.ext.request.loopme;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Value;

/**
* Defines the contract for bidrequest.imp[i].ext.loopme
*/
@AllArgsConstructor(staticName = "of")
@Value
@Value(staticConstructor = "of")
public class ExtImpLoopme {

@JsonProperty("accountId")
String accountId;
@JsonProperty("publisherId")
String publisherId;

@JsonProperty("bundleId")
String bundleId;

@JsonProperty("placementId")
String placementId;

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

import org.prebid.server.bidder.BidderDeps;
import org.prebid.server.bidder.loopme.LoopmeBidder;
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.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 javax.validation.constraints.NotBlank;

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

private static final String BIDDER_NAME = "loopme";

@Bean("loopmeConfigurationProperties")
@ConfigurationProperties("adapters.loopme")
BidderConfigurationProperties configurationProperties() {
return new BidderConfigurationProperties();
}

@Bean
BidderDeps loopmeBidderDeps(BidderConfigurationProperties loopmeConfigurationProperties,
@NotBlank @Value("${external-url}") String externalUrl,
JacksonMapper mapper) {
return BidderDepsAssembler.forBidder(BIDDER_NAME)
.withConfig(loopmeConfigurationProperties)
.usersyncerCreator(UsersyncerCreator.create(externalUrl))
.bidderCreator(config -> new LoopmeBidder(loopmeConfigurationProperties.getEndpoint(), mapper))
.assemble();
}
}
15 changes: 0 additions & 15 deletions src/main/resources/bidder-config/generic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,6 @@ adapters:
- video
supported-vendors:
vendor-id: 0
loopme:
enabled: false
endpoint: http://prebid-eu.loopmertb.com
meta-info:
maintainer-email: [email protected]
app-media-types:
- banner
- video
- native
site-media-types:
- banner
- video
- native
supported-vendors:
vendor-id: 109
zeta_global_ssp:
enabled: false
endpoint: https://ssp.disqus.com/bid/prebid-server?sid=GET_SID_FROM_ZETA
Expand Down
23 changes: 23 additions & 0 deletions src/main/resources/bidder-config/loopme.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
adapters:
loopme:
endpoint: http://prebid.loopmertb.com
meta-info:
maintainer-email: [email protected]
app-media-types:
- banner
- video
- audio
- native
site-media-types:
- banner
- video
- audio
- native
supported-vendors:
vendor-id: 109
usersync:
url: https://csync.loopme.me/?pubid=11393&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redirect={{redirect_url}}
redirect-url: /setuid?bidder=loopme&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={udid}
cookie-family-name: loopme
type: redirect
support-cors: false
21 changes: 15 additions & 6 deletions src/main/resources/static/bidder-params/loopme.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@
"title": "Loopme Adapter Params",
"description": "A schema which validates params accepted by the Loopme adapter",
"type": "object",

"properties": {
"accountId": {
"publisherId": {
"type": "string",
"description": "Account ID"
"description": "An id which identifies Loopme partner",
"minLength": 1
},
"bundleId": {
"type": "string",
"description": "An id which identifies app/site in Loopme",
"minLength": 1
},
"placementId": {
"type": "string",
"description": "A placement id in Loopme",
"minLength": 1
}
},

"required": ["accountId"]
}
"required": ["publisherId", "bundleId", "placementId"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,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.loopme.meta-info.app-media-types" : "",
"adapters.generic.aliases.loopme.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" : "",
Expand Down
Loading

0 comments on commit db72a00

Please sign in to comment.