Repository navigation
GoAdserver: New Adapter - #4648
goadserver wants to merge 3 commits into
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Logb1f3FNVSzPCTMtqNc8A
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Logb1f3FNVSzPCTMtqNc8A
The GoAdserver endpoint accepts OpenRTB app requests (bundle, store url, device.ifa/lmt, instl, rwdd) on the same gateway, so the bidder now takes a site or an app: the publisher token goes on app.publisher.id when there is no site. Bidder config declares app banner, video and native. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Added app (in-app) support in af61fae, matching the Go adapter (prebid/prebid-server#5023): GoAdserver's endpoint accepts OpenRTB app requests on the same gateway, so the bidder now takes a site or an app and puts the publisher token on app.publisher.id when there is no site. Bidder config declares app banner, video and native. Unit tests for the app path and a second GoadserverTest integration case with an app request. |
| /** | ||
| * GoAdserver is a self-hosted, multi-tenant ad server. All requests go to one fixed GoAdserver gateway, which | ||
| * routes each to the publisher's deployment by the publisher token. Impressions are grouped by token and each | ||
| * group is sent with its token in site.publisher.id, or app.publisher.id for in-app requests. | ||
| */ |
| if (extImp == null) { | ||
| throw new PreBidException("imp %s: missing ext.bidder".formatted(imp.getId())); | ||
| } |
| return builder.build(); | ||
| } | ||
|
|
||
| // The GoAdserver endpoint reads an optional sub-identifier from imp.ext.goadserver.subid. |
| final BidRequest.BidRequestBuilder builder = request.toBuilder().imp(imps); | ||
| if (request.getSite() != null) { | ||
| builder.site(modifySite(request.getSite(), token)); | ||
| } else { | ||
| builder.app(modifyApp(request.getApp(), token)); | ||
| } | ||
| final BidRequest outgoingRequest = builder.build(); |
There was a problem hiding this comment.
final BidRequest outgoingRequest = request.toBuilder()
.imp(imps)
.site(modifySite(request.getSite(), token))
.app(modifyApp(request.getApp(), token))
.build();
private static Site modifySite(Site site, String token) {
return site != null
? site.toBuilder().publisher(withToken(site.getPublisher(), token)).build()
: null;
}
// same for app
| // Drops the Prebid.js targeting GoAdserver adds for its direct integration and keeps only the | ||
| // DSA transparency object, which Prebid Server validates and relays. |
| private static UnaryOperator<ExtImpGoadserver> identity() { | ||
| return ext -> ext; | ||
| } |
There was a problem hiding this comment.
???? Use UnaryOperator.identity. You can use static import for it
| } | ||
|
|
||
| private static BidRequest givenBidRequest(Imp... imps) { | ||
| return givenBidRequest(request -> request, imps); |
There was a problem hiding this comment.
request -> request -> identity()
| .page("https://publisher.example/article") | ||
| .publisher(Publisher.builder().id("pbs-account").name("Publisher").build()) | ||
| .build(); | ||
| return requestCustomizer.apply(BidRequest.builder().id("request-id").site(site).imp(List.of(imps))) |
There was a problem hiding this comment.
place apply(...) on new line
| .build(); | ||
| } | ||
|
|
||
| private static Imp givenImp(String impId, UnaryOperator<ExtImpGoadserver> extCustomizer) { |
There was a problem hiding this comment.
Why do you need customizer for immutable object? Add givenImp(impId) and givenImp(impId, ext) methods instead
| @Test | ||
| public void openrtb2AuctionShouldRespondWithBidsFromGoadserverForAppRequest() throws IOException, JSONException { | ||
| // given | ||
| WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/goadserver-exchange")) | ||
| .withRequestBody(equalToJson(jsonFrom("openrtb2/goadserver/test-goadserver-app-bid-request.json"))) | ||
| .willReturn(aResponse() | ||
| .withBody(jsonFrom("openrtb2/goadserver/test-goadserver-bid-response.json")))); | ||
|
|
||
| // when | ||
| final Response response = responseFor("openrtb2/goadserver/test-auction-goadserver-app-request.json", | ||
| Endpoint.openrtb2_auction); | ||
|
|
||
| // then | ||
| assertJsonEquals("openrtb2/goadserver/test-auction-goadserver-response.json", response, | ||
| singletonList("goadserver")); | ||
| } |
There was a problem hiding this comment.
No need for this test. It's already covered by units
🔧 Type of changes
✨ What's the context?
GoAdserver is a self-hosted, multi-tenant ad server. The Prebid.js adapter (
goadserver) is already in Prebid.js, with docs at https://docs.prebid.org/dev-docs/bidders/goadserver.html. This adds the Prebid Server Java adapter. The Go counterpart is prebid/prebid-server#5023.🧠 Rationale behind the change
https://pbs.goadserver.com/openrtb2/auction. GoAdserver's gateway routes each request to the publisher's deployment by the publisher token, so the adapter never builds a hostname from request data.token(required), plus optionalfloor(USD CPM, applied when the imp has no bidfloor) andsubid(string or integer, sent asimp.ext.goadserver.subid).site.publisher.id. Other publisher fields are kept.bid.mtype, falling back tobid.ext.prebid.type, which the endpoint sets on every bid. The endpoint's Prebid.js targeting ext is dropped andbid.ext.dsais kept forDsaEnforcer.site.page.🔎 New Bid Adapter Checklist
Bidder<BidRequest>and usesBidderUtil.defaultRequestsite.publisher.idandimp.ext, applies the floor param, and filters the response ext.GoadserverTest)🧪 Test plan
GoadserverBidderTest: 18 unit tests covering site-only, grouping by token, publisher override and creation, floor precedence, subid (string and number), missing token, invalid ext, the OpenRTB version header, mtype and ext-type resolution, DSA kept and targeting stripped, unsupported types, and the default currency.GoadserverTestintegration test against WireMock.BidderParamValidatorTestandBidderCatalogTestpass, and checkstyle reports 0 violations.🏎 Quality check
🤖 Generated with Claude Code
https://claude.ai/code/session_01Logb1f3FNVSzPCTMtqNc8A