-
Notifications
You must be signed in to change notification settings - Fork 762
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: Bidtheatre #4069
base: master
Are you sure you want to change the base?
New Adapter: Bidtheatre #4069
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package bidtheatre | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/prebid/openrtb/v20/openrtb2" | ||
"github.com/prebid/prebid-server/v3/adapters" | ||
"github.com/prebid/prebid-server/v3/config" | ||
"github.com/prebid/prebid-server/v3/errortypes" | ||
"github.com/prebid/prebid-server/v3/openrtb_ext" | ||
"github.com/prebid/prebid-server/v3/util/jsonutil" | ||
) | ||
|
||
type adapter struct { | ||
endpoint string | ||
} | ||
|
||
// Builder builds a new instance of the Bidtheatre 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) { | ||
requestJSON, err := jsonutil.Marshal(request) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
requestData := &adapters.RequestData{ | ||
Method: "POST", | ||
Uri: a.endpoint, | ||
Body: requestJSON, | ||
ImpIDs: openrtb_ext.GetImpIDs(request.Imp), | ||
} | ||
|
||
return []*adapters.RequestData{requestData}, nil | ||
} | ||
|
||
func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { | ||
var bidExt openrtb_ext.ExtBid | ||
if err := jsonutil.Unmarshal(bid.Ext, &bidExt); err == nil && bidExt.Prebid != nil { | ||
return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) | ||
} | ||
|
||
return "", &errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), | ||
} | ||
Comment on lines
+51
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add test coverage for these lines by adding a supplemental JSON test that contains a malformed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this were your polite way of saying these lines can't be reached or not.. because I seem to be unable to create a test that triggers them =) The code comes from your references implementation but would you prefer I remove them? |
||
} | ||
|
||
func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if adapters.IsResponseStatusCodeNoContent(responseData) { | ||
return nil, nil | ||
} | ||
|
||
if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
var response openrtb2.BidResponse | ||
if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil { | ||
return nil, []error{err} | ||
andreasgreen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) | ||
bidResponse.Currency = response.Cur | ||
for _, seatBid := range response.SeatBid { | ||
for i := range seatBid.Bid { | ||
resolveMacros(&seatBid.Bid[i]) | ||
bidType, err := getMediaTypeForBid(seatBid.Bid[i]) | ||
if err != nil { | ||
continue | ||
} | ||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &seatBid.Bid[i], | ||
BidType: bidType, | ||
}) | ||
} | ||
} | ||
return bidResponse, nil | ||
andreasgreen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func resolveMacros(bid *openrtb2.Bid) { | ||
if bid == nil { | ||
return | ||
} | ||
price := strconv.FormatFloat(bid.Price, 'f', -1, 64) | ||
bid.NURL = strings.Replace(bid.NURL, "${AUCTION_PRICE}", price, -1) | ||
bid.AdM = strings.Replace(bid.AdM, "${AUCTION_PRICE}", price, -1) | ||
andreasgreen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package bidtheatre | ||
andreasgreen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import ( | ||
"github.com/prebid/openrtb/v20/openrtb2" | ||
"github.com/prebid/prebid-server/v3/adapters/adapterstest" | ||
"github.com/prebid/prebid-server/v3/config" | ||
"github.com/prebid/prebid-server/v3/openrtb_ext" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderBidtheatre, config.Adapter{ | ||
Endpoint: "http://any.url"}, | ||
config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) | ||
|
||
if buildErr != nil { | ||
t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
} | ||
|
||
adapterstest.RunJSONBidderTest(t, "bidtheatretest", bidder) | ||
} | ||
|
||
andreasgreen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func TestGetBidTypes(t *testing.T) { | ||
mockBid := openrtb2.Bid{ | ||
ID: "mock-bid-id", | ||
ImpID: "mock-imp-id", | ||
Price: 1.23, | ||
AdID: "mock-ad-id", | ||
CrID: "mock-cr-id", | ||
DealID: "mock-deal-id", | ||
W: 980, | ||
H: 240, | ||
Ext: []byte(`{"prebid": {"type": "banner"}}`), | ||
BURL: "https://example.com/win-notify", | ||
Cat: []string{"IAB1"}, | ||
} | ||
|
||
actualBidTypeValue, _ := getMediaTypeForBid(mockBid) | ||
|
||
if actualBidTypeValue != openrtb_ext.BidTypeBanner { | ||
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", openrtb_ext.BidTypeBanner, actualBidTypeValue) | ||
} | ||
|
||
mockBid.Ext = []byte(`{"prebid": {"type": "video"}}`) | ||
|
||
actualBidTypeValue, _ = getMediaTypeForBid(mockBid) | ||
|
||
if actualBidTypeValue != openrtb_ext.BidTypeVideo { | ||
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", openrtb_ext.BidTypeVideo, actualBidTypeValue) | ||
} | ||
|
||
} | ||
|
||
func TestReplaceMacros(t *testing.T) { | ||
andreasgreen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
mockBid := openrtb2.Bid{ | ||
ID: "mock-bid-id", | ||
ImpID: "mock-imp-id", | ||
Price: 1.23, | ||
AdID: "mock-ad-id", | ||
CrID: "mock-cr-id", | ||
DealID: "mock-deal-id", | ||
W: 980, | ||
H: 240, | ||
Ext: []byte(`{"prebid": {"type": "banner"}}`), | ||
BURL: "https://example.com/win-notify", | ||
Cat: []string{"IAB1"}, | ||
AdM: "<script type=\"text/javascript\">\n var uri = 'https://adsby.bidtheatre.com/imp?z=27025&a=1915538&so=1&ex=36&eb=3672319&xs=940698616&wp=${AUCTION_PRICE}&su=unknown&es=prebid.org&tag=unspec_980_300&kuid=eab9340e-8731-4027-9ada-57b554c75501&dealId=&mp=&ma=eyJjZCI6ZmFsc2UsInN0IjoxLCJtbGF0Ijo1OS4zMjkzLCJhZGMiOi0xLCJtb3JnIjoidGVsaWEgbmV0d29yayBzZXJ2aWNlcyIsIm1sc2NvcmUiOjAuMDczMTkwMTc0OTk2ODUyODcsIm16aXAiOiIxMTEyMCIsImJpcCI6IjgxLjIyNy44Mi4yOCIsImFnaWQiOjM1NjI3MDIsIm1sbW9kZWwiOiJtYXN0ZXJfbWxfY2xrXzU0MyIsInVhIjoiY3VybFwvNy44Ny4wIiwiYnJyZSI6ImFiIiwibWxvbiI6MTguMDY4NiwibXJlZ2lvbiI6ImFiIiwiZHQiOjgsImJyY28iOiJzd2UiLCJtY2l0eSI6InN0b2NraG9sbSIsImJyY2kiOiJzdG9ja2hvbG0iLCJwYWdldXJsIjoicHJlYmlkLm9yZyIsImltcGlkIjoieDM2X2FzeC1iLXMyXzc4MTc1MTk2NTcxMDMzNjUyMDciLCJtY291bnRyeSI6InN3ZSIsInRzIjoxNzMyMTEyNzMxNjgyfQ%3D%3D&usersync=1&cd=0&impId=x36_asx-b-s2_7817519657103365207&gdpr=0&gdpr_consent=&cb0=&rnd=' + new String (Math.random()).substring (2, 11);\n document.write('<sc'+'ript type=\"text/javascript\" src=\"'+uri+'\" charset=\"ISO-8859-1\"></sc'+'ript>');\n</script>", | ||
NURL: "https://adsby.bidtheatre.com/video?z=27025;a=1922926;ex=36;es=prebid.org;eb=3672319;xs=940698616;so=1;tag=unspec_640_360;kuid=1d10dda6-740d-4386-94a0-7042b2ad2a66;wp=${AUCTION_PRICE};su=unknown;iab=vast2;dealId=;ma=eyJjZCI6ZmFsc2UsInN0IjozLCJtbGF0Ijo1OS4zMjkzLCJhZGMiOi0xLCJtb3JnIjoidGVsaWEgbmV0d29yayBzZXJ2aWNlcyIsIm1sc2NvcmUiOjkuNTY5ODA3NDQzNzY3Nzg2RS00LCJtemlwIjoiMTExMjAiLCJiaXAiOiI4MS4yMjcuODIuMjgiLCJhZ2lkIjozNTYyNzAyLCJtbG1vZGVsIjoibWFzdGVyX21sX2Nsa181NDMiLCJ1YSI6ImN1cmxcLzcuODcuMCIsImJycmUiOiJhYiIsIm1sb24iOjE4LjA2ODYsIm1yZWdpb24iOiJhYiIsImR0Ijo4LCJicmNvIjoic3dlIiwibWNpdHkiOiJzdG9ja2hvbG0iLCJicmNpIjoic3RvY2tob2xtIiwicGFnZXVybCI6InByZWJpZC5vcmciLCJpbXBpZCI6IngzNl9hc3gtYi1zMV8yNTY5OTI0ODYzMjY2ODA4OTM2IiwibWNvdW50cnkiOiJzd2UiLCJ0cyI6MTczMjA5NjgyNjg5OH0%3D;cd=0;cb0=;impId=x36_asx-b-s1_2569924863266808936;gdpr=0;gdpr_consent=", | ||
} | ||
|
||
resolveMacros(&mockBid) | ||
|
||
if !strings.Contains(mockBid.AdM, "&wp=1.23&") { | ||
t.Errorf("AdM ${AUCTION_PRICE} not correctly replaced") | ||
} | ||
|
||
if strings.Contains(mockBid.AdM, "${AUCTION_PRICE}") { | ||
t.Errorf("AdM ${AUCTION_PRICE} not correctly replaced") | ||
} | ||
|
||
if !strings.Contains(mockBid.NURL, ";wp=1.23;") { | ||
t.Errorf("NURL ${AUCTION_PRICE} not correctly replaced") | ||
} | ||
|
||
if strings.Contains(mockBid.NURL, "${AUCTION_PRICE}") { | ||
t.Errorf("NURL ${AUCTION_PRICE} not correctly replaced") | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"banner": { | ||
"format": [ | ||
{ | ||
"w": 980, | ||
"h": 240 | ||
}, | ||
{ | ||
"w": 980, | ||
"h": 300 | ||
} | ||
] | ||
}, | ||
"ext": { | ||
"bidder": { | ||
"publisherId": "73b20b3a-12a0-4869-b54e-8d42b55786ee" | ||
} | ||
} | ||
} | ||
], | ||
"site": { | ||
"page": "prebid.org" | ||
}, | ||
"device": { | ||
"ip": "81.227.82.28" | ||
} | ||
}, | ||
|
||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"uri": "http://any.url", | ||
"body": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"banner": { | ||
"format": [ | ||
{ | ||
"w": 980, | ||
"h": 240 | ||
}, | ||
{ | ||
"w": 980, | ||
"h": 300 | ||
} | ||
] | ||
}, | ||
"ext": { | ||
"bidder": { | ||
"publisherId": "73b20b3a-12a0-4869-b54e-8d42b55786ee" | ||
} | ||
} | ||
} | ||
], | ||
"site": { | ||
"page": "prebid.org" | ||
}, | ||
"device": { | ||
"ip": "81.227.82.28" | ||
} | ||
}, | ||
"impIDs":["test-imp-id"] | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"cur": "USD", | ||
"seatbid": [ | ||
{ | ||
"seat": "5", | ||
"bid": [ | ||
{ | ||
"id": "test-imp-id", | ||
"impid": "test-imp-id", | ||
"price": 5.08712911605835, | ||
"adm": "<script type=\"text\/javascript\">\n var uri = 'https:\/\/adsby.bidtheatre.com\/imp?z=27025&a=1915538&so=1&ex=36&eb=3672319&xs=940698616&wp=${AUCTION_PRICE}&su=unknown&es=prebid.org&tag=unspec_980_300&kuid=eab9340e-8731-4027-9ada-57b554c75501&dealId=&mp=&ma=eyJjZCI6ZmFsc2UsInN0IjoxLCJtbGF0Ijo1OS4zMjkzLCJhZGMiOi0xLCJtb3JnIjoidGVsaWEgbmV0d29yayBzZXJ2aWNlcyIsIm1sc2NvcmUiOjAuMDczMTkwMTc0OTk2ODUyODcsIm16aXAiOiIxMTEyMCIsImJpcCI6IjgxLjIyNy44Mi4yOCIsImFnaWQiOjM1NjI3MDIsIm1sbW9kZWwiOiJtYXN0ZXJfbWxfY2xrXzU0MyIsInVhIjoiY3VybFwvNy44Ny4wIiwiYnJyZSI6ImFiIiwibWxvbiI6MTguMDY4NiwibXJlZ2lvbiI6ImFiIiwiZHQiOjgsImJyY28iOiJzd2UiLCJtY2l0eSI6InN0b2NraG9sbSIsImJyY2kiOiJzdG9ja2hvbG0iLCJwYWdldXJsIjoicHJlYmlkLm9yZyIsImltcGlkIjoieDM2X2FzeC1iLXMyXzc4MTc1MTk2NTcxMDMzNjUyMDciLCJtY291bnRyeSI6InN3ZSIsInRzIjoxNzMyMTEyNzMxNjgyfQ%3D%3D&usersync=1&cd=0&impId=x36_asx-b-s2_7817519657103365207&gdpr=0&gdpr_consent=&cb0=&rnd=' + new String (Math.random()).substring (2, 11);\n document.write('<sc'+'ript type=\"text\/javascript\" src=\"'+uri+'\" charset=\"ISO-8859-1\"><\/sc'+'ript>');\n<\/script>", | ||
"adid": "1915538", | ||
"cid": "c154375", | ||
"crid": "1915538", | ||
"w": 980, | ||
"h": 240, | ||
"ext": { | ||
"prebid": { | ||
"type": "banner" | ||
} | ||
} | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
], | ||
"expectedBidResponses": [ | ||
{ | ||
"bids":[ | ||
{ | ||
"currency": "USD", | ||
"bid": { | ||
"id": "test-imp-id", | ||
"impid": "test-imp-id", | ||
"price": 5.08712911605835, | ||
"adm": "<script type=\"text\/javascript\">\n var uri = 'https:\/\/adsby.bidtheatre.com\/imp?z=27025&a=1915538&so=1&ex=36&eb=3672319&xs=940698616&wp=5.08712911605835&su=unknown&es=prebid.org&tag=unspec_980_300&kuid=eab9340e-8731-4027-9ada-57b554c75501&dealId=&mp=&ma=eyJjZCI6ZmFsc2UsInN0IjoxLCJtbGF0Ijo1OS4zMjkzLCJhZGMiOi0xLCJtb3JnIjoidGVsaWEgbmV0d29yayBzZXJ2aWNlcyIsIm1sc2NvcmUiOjAuMDczMTkwMTc0OTk2ODUyODcsIm16aXAiOiIxMTEyMCIsImJpcCI6IjgxLjIyNy44Mi4yOCIsImFnaWQiOjM1NjI3MDIsIm1sbW9kZWwiOiJtYXN0ZXJfbWxfY2xrXzU0MyIsInVhIjoiY3VybFwvNy44Ny4wIiwiYnJyZSI6ImFiIiwibWxvbiI6MTguMDY4NiwibXJlZ2lvbiI6ImFiIiwiZHQiOjgsImJyY28iOiJzd2UiLCJtY2l0eSI6InN0b2NraG9sbSIsImJyY2kiOiJzdG9ja2hvbG0iLCJwYWdldXJsIjoicHJlYmlkLm9yZyIsImltcGlkIjoieDM2X2FzeC1iLXMyXzc4MTc1MTk2NTcxMDMzNjUyMDciLCJtY291bnRyeSI6InN3ZSIsInRzIjoxNzMyMTEyNzMxNjgyfQ%3D%3D&usersync=1&cd=0&impId=x36_asx-b-s2_7817519657103365207&gdpr=0&gdpr_consent=&cb0=&rnd=' + new String (Math.random()).substring (2, 11);\n document.write('<sc'+'ript type=\"text\/javascript\" src=\"'+uri+'\" charset=\"ISO-8859-1\"><\/sc'+'ript>');\n<\/script>", | ||
"adid": "1915538", | ||
"cid": "c154375", | ||
"crid": "1915538", | ||
"w": 980, | ||
"h": 240, | ||
"ext": { | ||
"prebid": { | ||
"type": "banner" | ||
} | ||
} | ||
}, | ||
"type": "banner" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what happend if we add muli-format, multi-imps ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mock impression already is multi-format, you want me to add mock impression requests that's multi-imp? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider this as a suggestion. Prebid server expects the media type to be explicitly set in the adapter response. Therefore, recommends implementing a pattern where the adapter server sets the MType field in the response to accurately determine the media type for the impression.