diff --git a/adapters/33across/33across.go b/adapters/33across/33across.go index eb6e67ac5d7..b9655faab7f 100644 --- a/adapters/33across/33across.go +++ b/adapters/33across/33across.go @@ -17,14 +17,31 @@ type TtxAdapter struct { } type Ext struct { - Ttx ext `json:"ttx"` + Ttx impTtxExt `json:"ttx"` } -type ext struct { +type impTtxExt struct { Prod string `json:"prod"` Zoneid string `json:"zoneid,omitempty"` } +type reqExt struct { + Ttx *reqTtxExt `json:"ttx,omitempty"` +} + +type reqTtxExt struct { + Caller []TtxCaller `json:"caller,omitempty"` +} + +type TtxCaller struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +// CALLER Info used to track Prebid Server +// as one of the hops in the request to exchange +var CALLER = TtxCaller{"Prebid-Server", "n/a"} + type bidExt struct { Ttx bidTtxExt `json:"ttx,omitempty"` } @@ -38,39 +55,41 @@ func (a *TtxAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters var errs []error var adapterRequests []*adapters.RequestData - adapterReq, errors := a.makeRequest(request) - if adapterReq != nil { - adapterRequests = append(adapterRequests, adapterReq) + // Construct request extension common to all imps + // NOTE: not blocking adapter requests on errors + // since request extension is optional. + reqExt, err := makeReqExt(request) + if err != nil { + errs = append(errs, err) + } + request.Ext = reqExt + + // Break up multi-imp request into multiple external requests since we don't + // support SRA in our exchange server + for i := 0; i < len(request.Imp); i++ { + if adapterReq, err := a.makeRequest(*request, request.Imp[i]); err == nil { + adapterRequests = append(adapterRequests, adapterReq) + } else { + errs = append(errs, err) + } } - errs = append(errs, errors...) - return adapterRequests, errors + return adapterRequests, errs } -// Update the request object to include custom value -// site.id -func (a *TtxAdapter) makeRequest(request *openrtb.BidRequest) (*adapters.RequestData, []error) { - var errs []error +func (a *TtxAdapter) makeRequest(request openrtb.BidRequest, imp openrtb.Imp) (*adapters.RequestData, error) { + impCopy, err := makeImps(imp) - // Make a copy as we don't want to change the original request - reqCopy := *request - if err := preprocess(&reqCopy); err != nil { - errs = append(errs, err) + if err != nil { + return nil, err } - if reqCopy.Imp[0].Banner == nil && reqCopy.Imp[0].Video == nil { - errs = append(errs, &errortypes.BadInput{ - Message: "At least one of [banner, video] formats must be defined in Imp. None found", - }) - - return nil, errs - } + request.Imp = []openrtb.Imp{*impCopy} // Last Step - reqJSON, err := json.Marshal(reqCopy) + reqJSON, err := json.Marshal(request) if err != nil { - errs = append(errs, err) - return nil, errs + return nil, err } headers := http.Header{} @@ -81,22 +100,26 @@ func (a *TtxAdapter) makeRequest(request *openrtb.BidRequest) (*adapters.Request Uri: a.endpoint, Body: reqJSON, Headers: headers, - }, errs + }, nil } -// Mutate the request to get it ready to send to ttx. -func preprocess(request *openrtb.BidRequest) error { - var imp = &request.Imp[0] +func makeImps(imp openrtb.Imp) (*openrtb.Imp, error) { + if imp.Banner == nil && imp.Video == nil { + return nil, &errortypes.BadInput{ + Message: fmt.Sprintf("Imp ID %s must have at least one of [Banner, Video] defined", imp.ID), + } + } + var bidderExt adapters.ExtImpBidder if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { - return &errortypes.BadInput{ + return nil, &errortypes.BadInput{ Message: err.Error(), } } var ttxExt openrtb_ext.ExtImp33across if err := json.Unmarshal(bidderExt.Bidder, &ttxExt); err != nil { - return &errortypes.BadInput{ + return nil, &errortypes.BadInput{ Message: err.Error(), } } @@ -104,26 +127,21 @@ func preprocess(request *openrtb.BidRequest) error { var impExt Ext impExt.Ttx.Prod = ttxExt.ProductId - // Add zoneid if it's defined + impExt.Ttx.Zoneid = ttxExt.SiteId + if len(ttxExt.ZoneId) > 0 { impExt.Ttx.Zoneid = ttxExt.ZoneId } impExtJSON, err := json.Marshal(impExt) if err != nil { - return &errortypes.BadInput{ + return nil, &errortypes.BadInput{ Message: err.Error(), } } imp.Ext = impExtJSON - if request.Site != nil { - siteCopy := *request.Site - siteCopy.ID = ttxExt.SiteId - request.Site = &siteCopy - } - // Validate Video if it exists if imp.Video != nil { videoCopy, err := validateVideoParams(imp.Video, impExt.Ttx.Prod) @@ -131,13 +149,35 @@ func preprocess(request *openrtb.BidRequest) error { imp.Video = videoCopy if err != nil { - return &errortypes.BadInput{ + return nil, &errortypes.BadInput{ Message: err.Error(), } } } - return nil + return &imp, nil +} + +func makeReqExt(request *openrtb.BidRequest) ([]byte, error) { + var reqExt reqExt + + if len(request.Ext) > 0 { + if err := json.Unmarshal(request.Ext, &reqExt); err != nil { + return nil, err + } + } + + if reqExt.Ttx == nil { + reqExt.Ttx = &reqTtxExt{} + } + + if reqExt.Ttx.Caller == nil { + reqExt.Ttx.Caller = make([]TtxCaller, 0) + } + + reqExt.Ttx.Caller = append(reqExt.Ttx.Caller, CALLER) + + return json.Marshal(reqExt) } // MakeBids make the bids for the bid response. diff --git a/adapters/33across/33acrosstest/exemplary/app-video.json b/adapters/33across/33acrosstest/exemplary/app-video.json deleted file mode 100644 index c3902107acc..00000000000 --- a/adapters/33across/33acrosstest/exemplary/app-video.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "mockBidRequest": { - "id": "test-request-id", - "imp": [ - { - "id": "test-imp-id", - "video": { - "w": 728, - "h": 90, - "protocols": [2], - "placement": 1, - "startdelay": -2, - "playbackmethod": [2], - "mimes": ["foo", "bar"] - }, - "ext": { - "bidder": { - "siteId": "fake-site-id", - "productId": "instream" - } - } - } - ], - "app": { - "id": "some-app-id" - } - }, - - "httpCalls": [ - { - "expectedRequest": { - "uri": "http://ssc.33across.com", - "body": { - "id": "test-request-id", - "imp": [ - { - "id":"test-imp-id", - "video": { - "w": 728, - "h": 90, - "protocols": [2], - "placement": 1, - "startdelay": -2, - "playbackmethod": [2], - "mimes": ["foo", "bar"] - }, - "ext": { - "ttx": { - "prod": "instream" - } - } - } - ], - "app": { - "id": "some-app-id" - } - } - }, - "mockResponse": { - "status": 200, - "body": { - "id": "test-request-id", - "seatbid": [ - { - "seat": "ttx", - "bid": [{ - "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", - "price": 0.500000, - "adm": "some-test-vast-ad", - "crid": "crid_10", - "h": 90, - "w": 728, - "ext": { - "ttx": { - "mediaType": "video" - } - } - }] - } - ], - "cur": "USD" - } - } - } - ], - - "expectedBidResponses": [ - { - "currency": "USD", - "bids": [ - { - "bid": { - "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", - "price": 0.5, - "adm": "some-test-vast-ad", - "crid": "crid_10", - "w": 728, - "h": 90, - "ext": { - "ttx": { - "mediaType": "video" - } - } - }, - "type": "video" - } - ] - } - ] -} diff --git a/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json b/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json index bb0e6585fd0..50fba69bde1 100644 --- a/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json +++ b/adapters/33across/33acrosstest/exemplary/bidresponse-defaults.json @@ -29,6 +29,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -44,14 +54,13 @@ }, "ext": { "ttx": { - "prod": "instream" + "prod": "instream", + "zoneid": "fake-site-id" } } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json b/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json index 479b197077a..c99e535cdb7 100644 --- a/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json +++ b/adapters/33across/33acrosstest/exemplary/instream-video-defaults.json @@ -27,6 +27,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -42,14 +52,13 @@ }, "ext": { "ttx": { - "prod": "instream" + "prod": "instream", + "zoneid": "fake-site-id" } } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/multi-format.json b/adapters/33across/33acrosstest/exemplary/multi-format.json index db15955ca87..3315ff72559 100644 --- a/adapters/33across/33acrosstest/exemplary/multi-format.json +++ b/adapters/33across/33acrosstest/exemplary/multi-format.json @@ -30,6 +30,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -47,14 +57,13 @@ }, "ext": { "ttx": { - "prod": "inview" + "prod": "inview", + "zoneid": "fake-site-id" } } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/multi-imp-banner.json b/adapters/33across/33acrosstest/exemplary/multi-imp-banner.json new file mode 100644 index 00000000000..b6d19f55683 --- /dev/null +++ b/adapters/33across/33acrosstest/exemplary/multi-imp-banner.json @@ -0,0 +1,200 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id1", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "fake-site-id", + "productId": "inview" + } + } + }, + { + "id": "test-imp-id2", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "bidder": { + "siteId": "fake-site-id", + "productId": "inview" + } + } + } + ], + "site": {} + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://ssc.33across.com", + "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id1", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "ttx": { + "prod": "inview", + "zoneid": "fake-site-id" + } + } + } + ], + "site": {} + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "ttx", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id1", + "price": 0.500000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "ttx": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + }, + { + "expectedRequest": { + "uri": "http://ssc.33across.com", + "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id2", + "banner": { + "format": [{"w": 728, "h": 90}] + }, + "ext": { + "ttx": { + "prod": "inview", + "zoneid": "fake-site-id" + } + } + } + ], + "site": {} + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "ttx", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id2", + "price": 0.600000, + "adm": "some-test-ad", + "crid": "crid_10", + "h": 90, + "w": 728, + "ext": { + "ttx": { + "mediaType": "banner" + } + } + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id1", + "price": 0.5, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "ttx": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + }, + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id2", + "price": 0.6, + "adm": "some-test-ad", + "crid": "crid_10", + "w": 728, + "h": 90, + "ext": { + "ttx": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/33across/33acrosstest/exemplary/optional-params.json b/adapters/33across/33acrosstest/exemplary/optional-params.json index 10b08497098..f429f9458a7 100644 --- a/adapters/33across/33acrosstest/exemplary/optional-params.json +++ b/adapters/33across/33acrosstest/exemplary/optional-params.json @@ -24,6 +24,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -39,9 +49,7 @@ } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json b/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json index c0c31168684..fdd422c7a63 100644 --- a/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json +++ b/adapters/33across/33acrosstest/exemplary/outstream-video-defaults.json @@ -27,6 +27,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -41,14 +51,13 @@ }, "ext": { "ttx": { - "prod": "siab" + "prod": "siab", + "zoneid": "fake-site-id" } } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/site-banner.json b/adapters/33across/33acrosstest/exemplary/site-banner.json index d8c215c06ae..552daf25224 100644 --- a/adapters/33across/33acrosstest/exemplary/site-banner.json +++ b/adapters/33across/33acrosstest/exemplary/site-banner.json @@ -23,6 +23,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -32,14 +42,13 @@ }, "ext": { "ttx": { - "prod": "inview" + "prod": "inview", + "zoneid": "fake-site-id" } } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/site-video.json b/adapters/33across/33acrosstest/exemplary/site-video.json index 55337b92827..3cf44775efb 100644 --- a/adapters/33across/33acrosstest/exemplary/site-video.json +++ b/adapters/33across/33acrosstest/exemplary/site-video.json @@ -29,6 +29,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -44,14 +54,13 @@ }, "ext": { "ttx": { - "prod": "instream" + "prod": "instream", + "zoneid": "fake-site-id" } } } ], - "site": { - "id": "fake-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/exemplary/app-banner.json b/adapters/33across/33acrosstest/supplemental/multi-imp-mixed-validation.json similarity index 69% rename from adapters/33across/33acrosstest/exemplary/app-banner.json rename to adapters/33across/33acrosstest/supplemental/multi-imp-mixed-validation.json index cd4ab085400..a2bc7890e96 100644 --- a/adapters/33across/33acrosstest/exemplary/app-banner.json +++ b/adapters/33across/33acrosstest/supplemental/multi-imp-mixed-validation.json @@ -3,7 +3,7 @@ "id": "test-request-id", "imp": [ { - "id": "test-imp-id", + "id": "test-imp-id1", "banner": { "format": [{"w": 728, "h": 90}] }, @@ -13,11 +13,18 @@ "productId": "inview" } } + }, + { + "id": "test-imp-id2", + "ext": { + "bidder": { + "siteId": "fake-site-id", + "productId": "inview" + } + } } ], - "app": { - "id": "some-app-id" - } + "site": {} }, "httpCalls": [ @@ -25,23 +32,32 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { - "id":"test-imp-id", + "id":"test-imp-id1", "banner": { "format": [{"w": 728, "h": 90}] }, "ext": { "ttx": { - "prod": "inview" + "prod": "inview", + "zoneid": "fake-site-id" } } } ], - "app": { - "id": "some-app-id" - } + "site": {} } }, "mockResponse": { @@ -53,7 +69,7 @@ "seat": "ttx", "bid": [{ "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", + "impid": "test-imp-id1", "price": 0.500000, "adm": "some-test-ad", "crid": "crid_10", @@ -72,7 +88,12 @@ } } ], - + "expectedMakeRequestsErrors": [ + { + "value": "Imp ID test-imp-id2 must have at least one of [Banner, Video] defined", + "comparison": "literal" + } + ], "expectedBidResponses": [ { "currency": "USD", @@ -80,7 +101,7 @@ { "bid": { "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", - "impid": "test-imp-id", + "impid": "test-imp-id1", "price": 0.5, "adm": "some-test-ad", "crid": "crid_10", diff --git a/adapters/33across/33acrosstest/supplemental/status-not-ok.json b/adapters/33across/33acrosstest/supplemental/status-not-ok.json index 98fe01c2e50..2c7fcd013f3 100644 --- a/adapters/33across/33acrosstest/supplemental/status-not-ok.json +++ b/adapters/33across/33acrosstest/supplemental/status-not-ok.json @@ -23,6 +23,16 @@ "expectedRequest": { "uri": "http://ssc.33across.com", "body": { + "ext": { + "ttx": { + "caller": [ + { + "name": "Prebid-Server", + "version": "n/a" + } + ] + } + }, "id": "test-request-id", "imp": [ { @@ -32,14 +42,13 @@ }, "ext": { "ttx": { - "prod": "inview" + "prod": "inview", + "zoneid": "fake-invalid-site-id" } } } ], - "site": { - "id": "fake-invalid-site-id" - } + "site": {} } }, "mockResponse": { diff --git a/adapters/33across/33acrosstest/supplemental/video-validation-fail.json b/adapters/33across/33acrosstest/supplemental/video-validation-fail.json index 97cb79bd26c..f29d728c9d7 100644 --- a/adapters/33across/33acrosstest/supplemental/video-validation-fail.json +++ b/adapters/33across/33acrosstest/supplemental/video-validation-fail.json @@ -23,10 +23,6 @@ { "value": "One or more invalid or missing video field(s) w, h, protocols, mimes, playbackmethod", "comparison": "literal" - }, - { - "value": "At least one of [banner, video] formats must be defined in Imp. None found", - "comparison": "literal" } ] } diff --git a/static/bidder-info/33across.yaml b/static/bidder-info/33across.yaml index 67e6996accf..e3eea765556 100644 --- a/static/bidder-info/33across.yaml +++ b/static/bidder-info/33across.yaml @@ -1,10 +1,6 @@ maintainer: email: "headerbidding@33across.com" capabilities: - app: - mediaTypes: - - banner - - video site: mediaTypes: - banner