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
89 changes: 89 additions & 0 deletions adapters/kargo/kargo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package kargo

import (
"encoding/json"
"fmt"
"net/http"

"github.com/mxmCherry/openrtb/v15/openrtb2"
"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/errortypes"
"github.com/prebid/prebid-server/openrtb_ext"
)

type adapter struct {
URI string
}
type kargoExt struct {
MediaType string `json:"mediaType"`
}

// Builder builds a new instance of the Kargo adapter for the given bidder with the given config.
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
bidder := &adapter{
URI: config.Endpoint, // base url of bidding server
}
return bidder, nil
}

// MakeRequests creates outgoing requests to the Kargo bidding server.
func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
requestJSON, err := json.Marshal(request)
if err != nil {
return nil, []error{err}
}

requestData := &adapters.RequestData{
Method: "POST",
Uri: a.URI,
Body: requestJSON,
}

return []*adapters.RequestData{requestData}, nil
}

// MakeBids receives a bid response from the Kargo bidding server and creates bids for the publishers auction.
func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if responseData.StatusCode == http.StatusNoContent {
return nil, nil
}

if responseData.StatusCode != http.StatusOK {
err := &errortypes.BadServerResponse{
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode),
}
return nil, []error{err}
}

var response openrtb2.BidResponse
if err := json.Unmarshal(responseData.Body, &response); err != nil {
return nil, []error{err}
}

bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
bidResponse.Currency = response.Cur
for _, seatBid := range response.SeatBid {
for i, bid := range seatBid.Bid {
b := &adapters.TypedBid{
Bid: &seatBid.Bid[i],
BidType: getMediaTypeForBid(bid.Ext),
}
bidResponse.Bids = append(bidResponse.Bids, b)
}
}
return bidResponse, nil
}

func getMediaTypeForBid(ext json.RawMessage) openrtb_ext.BidType {
var impExt kargoExt
if err := json.Unmarshal(ext, &impExt); err == nil {
switch impExt.MediaType {
case string(openrtb_ext.BidTypeVideo):
return openrtb_ext.BidTypeVideo
case string(openrtb_ext.BidTypeNative):
return openrtb_ext.BidTypeNative
}
}
return openrtb_ext.BidTypeBanner
}
20 changes: 20 additions & 0 deletions adapters/kargo/kargo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package kargo

import (
"testing"

"github.com/prebid/prebid-server/adapters/adapterstest"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/openrtb_ext"
)

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(openrtb_ext.BidderKargo, config.Adapter{
Endpoint: "http://example.com/bid"})

if buildErr != nil {
t.Fatalf("Builder returned unexpected error %v", buildErr)
}

adapterstest.RunJSONBidderTest(t, "kargotest", bidder)
}
207 changes: 207 additions & 0 deletions adapters/kargo/kargotest/exemplary/banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
{
"mockBidRequest": {
"id": "5f4d1e01",
"at": 1,
"imp": [
{
"id": "8b1bdcca",
"banner": {
"w": 300,
"h": 300,
"format": [
{
"w": 300,
"h": 250
}
],
"pos": 0,
"expdir": [1, 2, 3, 4, 5]
},
"tagid": "73",
"secure": 1,
"iframebuster": ["ALL"],
"ext": {
"adSlotID": "11523"
}
}
],
"site": {
"id": "123",
"domain": "www.dailymail.co.uk",
"cat": ["IAB7"],
"page": "https://www.dailymail.co.uk/",
"ref": "https://www.dailymail.co.uk/",
"mobile": 1,
"publisher": {
"id": "1"
}
},
"device": {
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.1 Safari/537",
"geo": {
"ipservice": 4,
"country": "US",
"region": "CO",
"metro": "751",
"city": "SomeCityInCo",
"zip": "11223"
},
"ip": "127.0.0.1",
"devicetype": 2,
"make": "Apple",
"model": "iPhone",
"os": "Windows",
"osv": "10.0",
"carrier": "none",
"language": "en",
"connectiontype": 2,
"dnt": 0
},
"user": {
"id": "07fb48ed",
"ext": {
},
"buyeruid": "345"
},
"regs": {
"ext": {
"us_privacy": "1"
}
},
"tmax": 200,
"ext": {
}
},
"httpCalls": [
{
"expectedRequest": {
"uri": "http://example.com/bid",
"body": {
"id": "5f4d1e01",
"at": 1,
"imp": [
{
"id": "8b1bdcca",
"banner": {
"w": 300,
"h": 300,
"format": [
{
"w": 300,
"h": 250
}
],
"pos": 0,
"expdir": [1, 2, 3, 4, 5]
},
"tagid": "73",
"secure": 1,
"iframebuster": ["ALL"],
"ext": {
"adSlotID": "11523"
Copy link
Author

@ssadman22 ssadman22 Jun 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each impression will have an Imp.Ext.adSlotID and a Imp.tagid. Since the adSlotID is now required by Prebid S2S, Kraken can check this instead of appending "siteID" + . + "tagId" as shown here for Prebid requests:

}
}
],
"site": {
"id": "123",
"domain": "www.dailymail.co.uk",
"cat": ["IAB7"],
"page": "https://www.dailymail.co.uk/",
"ref": "https://www.dailymail.co.uk/",
"mobile": 1,
"publisher": {
"id": "1"
}
},
"device": {
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.1 Safari/537",
"geo": {
"ipservice": 4,
"country": "US",
"region": "CO",
"metro": "751",
"city": "SomeCityInCo",
"zip": "11223"
},
"ip": "127.0.0.1",
"devicetype": 2,
"make": "Apple",
"model": "iPhone",
"os": "Windows",
"osv": "10.0",
"carrier": "none",
"language": "en",
"connectiontype": 2,
"dnt": 0
},
"user": {
"id": "07fb48ed",
"ext": {
},
"buyeruid": "345"
},
"regs": {
"ext": {
"us_privacy": "1"
}
},
"tmax": 200,
"ext": {
}
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "5f4d1e01",
"seatbid": [
{
"bid": [
{
"id": "67sadsac",
"impid": "8b1bdcca",
"price": 10,
"nurl": "http://example.com/win/10",
"adm": "<div>ad</div>",
"adomain": ["example.com"],
"cid": "test-cid",
"crid": "test-crid",
"cat": ["IAB13"],
"w": 300,
"h": 300,
"ext": {"mediaType": "banner"}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will now be sending the mediaType back to prebid as it is required by the adapter

}
],
"seat": "_b345"
}
],
"bidid": "67sadsac",
"cur": "USD"
}
}
}
],
"expectedBidResponses": [
{
"bids": [
{
"bid": {
"id": "67sadsac",
"impid": "8b1bdcca",
"price": 10,
"nurl": "http://example.com/win/10",
"adm": "<div>ad</div>",
"adomain": ["example.com"],
"cid": "test-cid",
"crid": "test-crid",
"cat": ["IAB13"],
"w": 300,
"h": 300,
"ext": {"mediaType": "banner"}
},
"type": "banner"
}
]
}
]
}
Loading