Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Adapter: Concert #1

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f91e305
adds empty files for concert adapter
BrettBlox Apr 10, 2024
d34e432
adds placeholder config options
BrettBlox Apr 11, 2024
5aeb95f
omits gvlVendorId from config
BrettBlox Apr 11, 2024
b7a6fe3
removes dooh capability
BrettBlox Apr 11, 2024
7b5df75
removes native media types
BrettBlox Apr 11, 2024
33b8a4d
adds placeholder concert support email - to be confirmed
BrettBlox Apr 11, 2024
217570f
scaffolds out basic go adapter for concert
BrettBlox Apr 12, 2024
ad315c1
adds concert to adapter_builders and bidders lists
BrettBlox Apr 15, 2024
6be2f7d
translates prebidjs bidder params to prebid server schema for concert…
BrettBlox Apr 22, 2024
1161540
adds params struct file and updates adapter
BrettBlox Apr 22, 2024
b087828
extracts publisher id and forwards it in site object
BrettBlox Apr 22, 2024
b1de33e
runs format script
BrettBlox Apr 22, 2024
dffccd1
scaffolds test files
BrettBlox Apr 22, 2024
90e58ee
adds mock bid requests for each type
BrettBlox Apr 22, 2024
ed479ac
adds optional params from the prebid.js adapter
BrettBlox Apr 22, 2024
ca8dd13
updates params test to include optional parameters
BrettBlox Apr 22, 2024
701edba
fixes formatting
BrettBlox Apr 22, 2024
32b20c3
adds httpcalls to banner mock data
BrettBlox Apr 22, 2024
e8ed647
adds httpcalls to audio mock data
BrettBlox Apr 22, 2024
aaebf05
use correct endpoint
BrettBlox Apr 22, 2024
6a76468
adds remaining properties for audio, video, and banner ad mocks
BrettBlox Apr 23, 2024
7b75b30
adds additional invalid params entry
BrettBlox Apr 23, 2024
5fa8d32
removes publisher id logic
BrettBlox Apr 23, 2024
1d48f83
fixes json media type issue
BrettBlox Apr 23, 2024
ab5d56f
removes unused import
BrettBlox Apr 23, 2024
cc8ab0d
tests passing
BrettBlox Apr 23, 2024
2f3d2c9
updates endpoint for testing and adds contenty type header
BrettBlox Apr 24, 2024
ea30a3e
removes unused import
BrettBlox Apr 24, 2024
87ca22b
removes usersync from config file
BrettBlox Apr 29, 2024
48f22ec
adds adapterversion
BrettBlox Apr 29, 2024
df36d41
fixes go linting errors
BrettBlox Apr 29, 2024
67ffa72
removes comment
BrettBlox Apr 29, 2024
700ce40
removes comments
BrettBlox Apr 29, 2024
01c974b
adds optional parameters to imp ext struct
BrettBlox Apr 29, 2024
5d71877
formats impextconcert
BrettBlox Apr 29, 2024
8dba23b
use prod endpoint
BrettBlox Apr 29, 2024
0b435d2
uses partnerId for auth header to cbs
BrettBlox May 1, 2024
e3407bf
adds partner ID to top level ext and as auth header
BrettBlox May 1, 2024
8b4e828
update auth header
BrettBlox May 1, 2024
dbdc395
adds impids to makerequests return
BrettBlox May 2, 2024
3957010
fixes return statement
BrettBlox May 2, 2024
fcd880e
updates test json files with impids in request obj
BrettBlox May 2, 2024
ba289c2
removes authorization header - no longer needed in bidding server
BrettBlox May 2, 2024
364eb90
Checks MType
BrettBlox May 15, 2024
4c03143
fallback for mtype no longer needed
BrettBlox May 16, 2024
5642348
formatting
BrettBlox May 16, 2024
9c30265
updates error response handling in makebids
BrettBlox May 28, 2024
2c7b6f9
use response error message
BrettBlox May 28, 2024
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
164 changes: 164 additions & 0 deletions adapters/concert/concert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package concert

import (
"encoding/json"
"fmt"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/adapters"
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/errortypes"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"net/http"
)

type adapter struct {
endpoint string
}

const adapterVersion = "1.0.0"

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

func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
bidderImpExt, err := getBidderExt(request.Imp[0])
if err != nil {
return nil, []error{fmt.Errorf("get bidder ext: %v", err)}
}

requestJSON, err := json.Marshal(request)
if err != nil {
return nil, []error{err}
}

var requestMap map[string]interface{}
err = json.Unmarshal(requestJSON, &requestMap)
if err != nil {
return nil, []error{err}
}

if requestMap["ext"] == nil {
requestMap["ext"] = make(map[string]interface{})
}
requestMap["ext"].(map[string]interface{})["adapterVersion"] = adapterVersion
requestMap["ext"].(map[string]interface{})["partnerId"] = bidderImpExt.PartnerId

requestJSON, err = json.Marshal(requestMap)
if err != nil {
return nil, []error{err}
}

requestData := &adapters.RequestData{
Method: "POST",
Uri: a.endpoint,
Body: requestJSON,
Headers: http.Header{
"Content-Type": []string{"application/json"},
"Authorization": []string{"concert-prebid-server"},
},
}

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

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.StatusBadRequest {
err := &errortypes.BadInput{
Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.",
}
return nil, []error{err}
}

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
var errors []error
for _, seatBid := range response.SeatBid {
for i, bid := range seatBid.Bid {
imp, _ := getImpByID(bid.ImpID, request.Imp)
bidType, err := getMediaTypeForBid(bid, imp)
if err != nil {
errors = append(errors, err)
continue
}
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: &seatBid.Bid[i],
BidType: bidType,
})
}
}

if len(errors) > 0 {
return nil, errors
}

if len(bidResponse.Bids) == 0 {
return nil, []error{fmt.Errorf("no bids returned")}
}

return bidResponse, nil
}

func getImpByID(impID string, imps []openrtb2.Imp) (*openrtb2.Imp, error) {
for _, imp := range imps {
if imp.ID == impID {
return &imp, nil
}
}
return nil, fmt.Errorf("no matching imp found for id %s", impID)
}

func getMediaTypeForBid(bid openrtb2.Bid, imp *openrtb2.Imp) (openrtb_ext.BidType, error) {
if bid.Ext != nil {
var bidExt openrtb_ext.ExtBid
err := json.Unmarshal(bid.Ext, &bidExt)
if err == nil && bidExt.Prebid != nil {
return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type))
}
}

if imp != nil {
if imp.Video != nil {
return openrtb_ext.BidTypeVideo, nil
} else if imp.Banner != nil {
return openrtb_ext.BidTypeBanner, nil
} else if imp.Audio != nil {
return openrtb_ext.BidTypeAudio, nil
}
}

return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID),
}
}

func getBidderExt(imp openrtb2.Imp) (bidderImpExt openrtb_ext.ImpExtConcert, err error) {
var impExt adapters.ExtImpBidder
if err = json.Unmarshal(imp.Ext, &impExt); err != nil {
return bidderImpExt, fmt.Errorf("imp ext: %v", err)
}
if err = json.Unmarshal(impExt.Bidder, &bidderImpExt); err != nil {
return bidderImpExt, fmt.Errorf("bidder ext: %v", err)
}
return bidderImpExt, nil
}
20 changes: 20 additions & 0 deletions adapters/concert/concert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package concert

import (
"testing"

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

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(openrtb_ext.BidderConcert, config.Adapter{
Endpoint: "https://bids.concert.io/bids/openrtb"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})

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

adapterstest.RunJSONBidderTest(t, "concerttest", bidder)
}
116 changes: 116 additions & 0 deletions adapters/concert/concerttest/exemplary/audio.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"mockBidRequest": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"audio": {
"mimes": ["audio/mp3"],
"minduration": 5,
"maxduration": 30,
"protocols": [1, 2]
},
"ext": {
"bidder": {
"partnerId": "partner_name",
"placementId": 1234567,
"site": "site_name",
"slot": "slot_name"
}
}
}
],
"site": {
"page": "http://www.example.com"
},
"device": {
"ua": "test-user-agent",
"ip": "123.123.123.123"
},
"user": {
"buyeruid": "some-buyer-uid"
},
"ext": {
"adapterVersion": "1.0.0",
"partnerId": "partner_name"
}
},
"httpCalls": [
{
"expectedRequest": {
"uri": "https://bids.concert.io/bids/openrtb",
"body": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"audio": {
"mimes": ["audio/mp3"],
"minduration": 5,
"maxduration": 30,
"protocols": [1, 2]
},
"ext": {
"bidder": {
"partnerId": "partner_name",
"placementId": 1234567,
"site": "site_name",
"slot": "slot_name"
}
}
}
],
"device": {
"ip": "123.123.123.123",
"ua": "test-user-agent"
},
"site": {
"page": "http://www.example.com"
},
"user": {
"buyeruid": "some-buyer-uid"
},
"ext": {
"adapterVersion": "1.0.0",
"partnerId": "partner_name"
}
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-response-id",
"seatbid": [
{
"bid": [
{
"id": "test-bid-id",
"impid": "test-imp-id",
"price": 1.23,
"adm": "<VAST version=\"3.0\"><Ad><Wrapper>...</Wrapper></Ad></VAST>",
"crid": "test-creative-id"
}
]
}
]
}
}
}
],
"expectedBidResponses": [
{
"bids": [
{
"bid": {
"id": "test-bid-id",
"impid": "test-imp-id",
"price": 1.23,
"adm": "<VAST version=\"3.0\"><Ad><Wrapper>...</Wrapper></Ad></VAST>",
"crid": "test-creative-id"
},
"type": "audio"
}
]
}
]
}
Loading