From 52b65f4306128a64363ca6ea885a4f86aad722eb Mon Sep 17 00:00:00 2001 From: Andrea Fassina Date: Mon, 25 Nov 2024 17:31:10 +0100 Subject: [PATCH 1/9] feat: add nativery prebid adapter --- adapters/nativery/models.go | 62 ++++ adapters/nativery/nativery.go | 302 ++++++++++++++++++ adapters/nativery/nativery_test.go | 20 ++ .../nativerytest/exemplary/banner.json | 189 +++++++++++ .../nativerytest/exemplary/native.json | 179 +++++++++++ .../nativerytest/exemplary/video.json | 187 +++++++++++ .../nativerytest/supplemental/status_204.json | 97 ++++++ .../nativerytest/supplemental/status_400.json | 94 ++++++ adapters/nativery/params_test.go | 55 ++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_nativery.go | 8 + static/bidder-info/nativery.yaml | 12 + static/bidder-params/nativery.json | 15 + 14 files changed, 1224 insertions(+) create mode 100644 adapters/nativery/models.go create mode 100644 adapters/nativery/nativery.go create mode 100644 adapters/nativery/nativery_test.go create mode 100644 adapters/nativery/nativerytest/exemplary/banner.json create mode 100644 adapters/nativery/nativerytest/exemplary/native.json create mode 100644 adapters/nativery/nativerytest/exemplary/video.json create mode 100644 adapters/nativery/nativerytest/supplemental/status_204.json create mode 100644 adapters/nativery/nativerytest/supplemental/status_400.json create mode 100644 adapters/nativery/params_test.go create mode 100644 openrtb_ext/imp_nativery.go create mode 100644 static/bidder-info/nativery.yaml create mode 100644 static/bidder-params/nativery.json diff --git a/adapters/nativery/models.go b/adapters/nativery/models.go new file mode 100644 index 00000000000..cb3c6103534 --- /dev/null +++ b/adapters/nativery/models.go @@ -0,0 +1,62 @@ +package nativery + +type adapter struct { + endpoint string +} + +type refRef struct { + Page string `json:"page"` + Ref string `json:"ref"` +} + +// request body to send to widget server in ext +type nativeryExtReqBody struct { + Id string `json:"id"` //the placement/widget id + Xhr int `json:"xhr"` + V int `json:"v"` + Ref string `json:"ref"` + RefRef refRef `json:"refref"` +} + +type impExt struct { + Nativery nativeryExtReqBody `json:"nativery"` +} + +type bidReqExtNativery struct { + IsAMP bool `json:"isAmp"` + WidgetId string `json:"widgetId"` +} + +type ImpressionBody struct { + WidgetId string `json:"idw"` + UrlId string `json:"idu"` + ImpressionId string `json:"idi"` + AdIds []string `json:"ida"` + IsAMP bool `json:"isAmp"` + Ref string `json:"ref"` + RefRef string `json:"refref"` + SessionId string `json:"sid"` +} + +type ImpressionOptions struct { + Method string `json:"method"` + Body ImpressionBody `json:"body"` +} +type ImpressionData struct { + Url string `json:"url"` + Options ImpressionOptions `json:"options"` +} +type bidExtNativery struct { + BidType string `json:"bid_ad_media_type"` + BidAdvDomains []string `json:"bid_adv_domains"` + + AdvertiserId string `json:"adv_id,omitempty"` + BrandCategory int `json:"brand_category_id,omitempty"` + Impression ImpressionData `json:"impression"` + RealImpression ImpressionData `json:"realImpression"` + RealImpressionAd ImpressionData `json:"realImpressionAd"` +} + +type bidExt struct { + Nativery bidExtNativery `json:"nativery"` +} diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go new file mode 100644 index 00000000000..cf1684aaef0 --- /dev/null +++ b/adapters/nativery/nativery.go @@ -0,0 +1,302 @@ +package nativery + +import ( + "encoding/json" + "errors" + "fmt" + "maps" + "net/http" + + "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/metrics" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +// Function used to builds a new instance of the Nativery adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + // build bidder + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} + +// makeRequests creates HTTP requests for a given BidRequest and adapter configuration. +// It generates requests for each ad exchange targeted by the BidRequest, +// serializes the BidRequest into the request body, and sets the appropriate +// HTTP headers and other parameters. +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + reqCopy := *request + var errs []error + + // check if the request come from AMP + var isAMP int + if reqInfo.PbsEntryPoint == metrics.ReqTypeAMP { + isAMP = 1 + } + + var widgetId string + + // attach body request for all the impressions + validImps := []openrtb2.Imp{} + for i, imp := range request.Imp { + reqCopy.Imp = []openrtb2.Imp{imp} + + nativeryExt, err := buildNativeryExt(&reqCopy.Imp[0]) + if err != nil { + errs = append(errs, err) + continue + } + + // at the first impression set widgetId value + if i == 0 { + widgetId = nativeryExt.WidgetId + } + + if err := buildRequest(reqCopy, nativeryExt); err != nil { + errs = append(errs, err) + continue + } + + validImps = append(validImps, reqCopy.Imp...) + + } + + reqCopy.Imp = validImps + // If all the requests were malformed, don't bother making a server call with no impressions. + if len(reqCopy.Imp) == 0 { + return nil, errs + } + + reqExt, err := getRequestExt(reqCopy.Ext) + if err != nil { + return nil, append(errs, err) + } + + reqExtNativery, err := getNativeryExt(reqExt, isAMP, widgetId) + if err != nil { + return nil, append(errs, err) + } + // TODO: optimize it, we reiterate imp there and before + adapterRequests, errors := splitRequests(reqCopy.Imp, &reqCopy, reqExt, reqExtNativery, a.endpoint) + + return adapterRequests, append(errs, errors...) +} + +func buildNativeryExt(imp *openrtb2.Imp) (openrtb_ext.ImpExtNativery, error) { + var bidderExt adapters.ExtImpBidder + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + return openrtb_ext.ImpExtNativery{}, err + } + + var nativeryExt openrtb_ext.ImpExtNativery + if err := json.Unmarshal(bidderExt.Bidder, &nativeryExt); err != nil { + return openrtb_ext.ImpExtNativery{}, err + } + + return nativeryExt, nil +} + +// utility function used to build the body for the http request for a single impression +func buildRequest(reqCopy openrtb2.BidRequest, reqExt openrtb_ext.ImpExtNativery) error { + + impExt := impExt{Nativery: nativeryExtReqBody{ + Id: reqExt.WidgetId, + Xhr: 2, + V: 3, + // TODO: Site is only for browser request, we have to handle if the req comes from app or dooh + Ref: reqCopy.Site.Page, + RefRef: refRef{Page: reqCopy.Site.Page, Ref: reqCopy.Site.Ref}, + }} + + var err error + reqCopy.Imp[0].Ext, err = json.Marshal(&impExt) + + return err +} + +// makebids handles the entire bidding process for a single BidRequest. +// It creates and sends bid requests to multiple ad exchanges, receives +// and parses responses, extracts bids and other relevant information, +// and populates a BidderResponse object with the aggregated information. +func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + // check if the response has no content + if adapters.IsResponseStatusCodeNoContent(response) { + // Extract nativery no content reason if is present + reason := "" + if response.Headers != nil { + reason = response.Headers.Get("X-Nativery-Error") + } + if reason == "" { + reason = "No Content" + } + // Add the reason to errors + return nil, []error{errors.New(reason)} + } + + // check if the response has errors + if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { + return nil, []error{err} + } + + // handle response + var nativeryResponse openrtb2.BidResponse + if err := json.Unmarshal(response.Body, &nativeryResponse); err != nil { + return nil, []error{err} + } + + var errs []error + // create bidder with impressions length capacity + bidderResponse := adapters.NewBidderResponseWithBidsCapacity(len(internalRequest.Imp)) + for _, sb := range nativeryResponse.SeatBid { + for i := range sb.Bid { + bid := sb.Bid[i] + + // should be data sended from nativery server to partecipate to the auction + var bidExt bidExt + if err := json.Unmarshal(bid.Ext, &bidExt); err != nil { + errs = append(errs, err) + continue + } + + bidType, err := getMediaTypeForBid(&bidExt) + if err != nil { + errs = append(errs, err) + continue + } + // get metadata + bidMeta := buildBidMeta(string(bidType), bidExt.Nativery.BidAdvDomains) + + bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: bidType, + // metadata is encouraged + BidMeta: bidMeta, + }) + } + + } + + // set bidder currency, EUR by default + if nativeryResponse.Cur != "" { + bidderResponse.Currency = nativeryResponse.Cur + } else { + bidderResponse.Currency = "EUR" + } + return bidderResponse, errs + +} + +// getMediaTypeForBid switch nativery type in bid type. +func getMediaTypeForBid(bid *bidExt) (openrtb_ext.BidType, error) { + switch bid.Nativery.BidType { + case "native": + return openrtb_ext.BidTypeNative, nil + case "display", "banner", "rich_media": + return openrtb_ext.BidTypeBanner, nil + case "video": + return openrtb_ext.BidTypeVideo, nil + default: + return "", fmt.Errorf("unrecognized bid_ad_media_type in response from nativery: %s", bid.Nativery.BidType) + } +} + +func convertIntToBoolean(num *int) bool { + var b bool + // Dereferenzia num usando * + if num != nil && *num == 1 { + b = true + } else { + b = false + } + return b +} + +func buildBidMeta(mediaType string, advDomain []string) *openrtb_ext.ExtBidPrebidMeta { + + //advertiserDomains and dchain are encouraged to implements + return &openrtb_ext.ExtBidPrebidMeta{ + MediaType: mediaType, + AdvertiserDomains: advDomain, + /* + DChain: json.RawMessage{} , + Cosa include Dchain: + nodes: Un array di oggetti che rappresentano i diversi partecipanti alla catena di domanda. + complete: Un flag che indica se la catena di domanda è completa (1) o incompleta (0). + ver: La versione del modulo Dchain utilizzato. + */ + } +} + +func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExt map[string]json.RawMessage, requestExtNativery bidReqExtNativery, uri string) ([]*adapters.RequestData, []error) { + var errs []error + + resArr := make([]*adapters.RequestData, 0, 1) + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + + nativeryExtJson, err := json.Marshal(requestExtNativery) + if err != nil { + errs = append(errs, err) + } + + requestExtClone := maps.Clone(requestExt) + requestExtClone["nativery"] = nativeryExtJson + + request.Ext, err = json.Marshal(requestExtClone) + if err != nil { + errs = append(errs, err) + } + + for _, imp := range imps { + impsForReq := []openrtb2.Imp{imp} + request.Imp = impsForReq + + reqJSON, err := json.Marshal(request) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + resArr = append(resArr, &adapters.RequestData{ + Method: "POST", + Uri: uri, + Body: reqJSON, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + }) + } + return resArr, errs +} + +func getRequestExt(ext json.RawMessage) (map[string]json.RawMessage, error) { + extMap := make(map[string]json.RawMessage) + + if len(ext) > 0 { + if err := json.Unmarshal(ext, &extMap); err != nil { + return nil, err + } + } + + return extMap, nil +} + +func getNativeryExt(extMap map[string]json.RawMessage, isAMP int, widgetId string) (bidReqExtNativery, error) { + var nativeryExt bidReqExtNativery + + // if ext.nativery already exists return it + if nativeryExtJson, exists := extMap["nativery"]; exists && len(nativeryExtJson) > 0 { + if err := json.Unmarshal(nativeryExtJson, &nativeryExt); err != nil { + return nativeryExt, err + } + } + + nativeryExt.IsAMP = convertIntToBoolean(&isAMP) + nativeryExt.WidgetId = widgetId + + return nativeryExt, nil +} diff --git a/adapters/nativery/nativery_test.go b/adapters/nativery/nativery_test.go new file mode 100644 index 00000000000..4875089fea4 --- /dev/null +++ b/adapters/nativery/nativery_test.go @@ -0,0 +1,20 @@ +package nativery + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderNativery, config.Adapter{ + Endpoint: "http://example.com/hb"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "nativerytest", bidder) +} diff --git a/adapters/nativery/nativerytest/exemplary/banner.json b/adapters/nativery/nativerytest/exemplary/banner.json new file mode 100644 index 00000000000..582dcc9d075 --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/banner.json @@ -0,0 +1,189 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/exemplary/native.json b/adapters/nativery/nativerytest/exemplary/native.json new file mode 100644 index 00000000000..63359efa8ac --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/native.json @@ -0,0 +1,179 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"context\":1,\"plcmttype\":1,\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"type\":3,\"w\":120,\"h\":100}},{\"id\":1,\"required\":1,\"title\":{\"len\":140}},{\"id\":2,\"data\":{\"type\":1}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"context\":1,\"plcmttype\":1,\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"type\":3,\"w\":120,\"h\":100}},{\"id\":1,\"required\":1,\"title\":{\"len\":140}},{\"id\":2,\"data\":{\"type\":1}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1]}]}", + "ver": "1.2" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":3,\"required\":1,\"img\":{\"url\":\"http://example.com/img/url\",\"w\":120,\"h\":100}},{\"id\":0,\"required\":1,\"title\":{\"text\":\"Test title\"}},{\"id\":5,\"data\":{\"value\":\"Test sponsor\"}}],\"link\":{\"url\":\"http://example.com/click/url\"},\"imptrackers\":[\"http://example.com/impression\"],\"jstracker\":\"\\u003cscript src=\\\"http://example.com/impression\\\"\\u003e\\u003c/script\\u003e\"}", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 4, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":3,\"required\":1,\"img\":{\"url\":\"http://example.com/img/url\",\"w\":120,\"h\":100}},{\"id\":0,\"required\":1,\"title\":{\"text\":\"Test title\"}},{\"id\":5,\"data\":{\"value\":\"Test sponsor\"}}],\"link\":{\"url\":\"http://example.com/click/url\"},\"imptrackers\":[\"http://example.com/impression\"],\"jstracker\":\"\\u003cscript src=\\\"http://example.com/impression\\\"\\u003e\\u003c/script\\u003e\"}", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 4, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/exemplary/video.json b/adapters/nativery/nativerytest/exemplary/video.json new file mode 100644 index 00000000000..e0f9831aac2 --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/video.json @@ -0,0 +1,187 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "minduration": 15, + "maxduration": 30, + "protocols": [2, 3, 5, 6, 7, 8], + "w": 940, + "h": 560 + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "minduration": 15, + "maxduration": 30, + "protocols": [2, 3, 5, 6, 7, 8], + "w": 940, + "h": 560 + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": " ...", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 2, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "video", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": " ...", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 2, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "video", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/supplemental/status_204.json b/adapters/nativery/nativerytest/supplemental/status_204.json new file mode 100644 index 00000000000..4a53616c0ef --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/status_204.json @@ -0,0 +1,97 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 204, + "body": {}, + "error": ["No Content"] + } + } + ], + + "expectedBidResponses": [], + + "expectedMakeBidsErrors": [ + { + "value": "No Content", + "comparison": "literal" + } + ] +} diff --git a/adapters/nativery/nativerytest/supplemental/status_400.json b/adapters/nativery/nativerytest/supplemental/status_400.json new file mode 100644 index 00000000000..5364f6e144c --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/status_400.json @@ -0,0 +1,94 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 400, + "body": {} + } + } + ], + + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/nativery/params_test.go b/adapters/nativery/params_test.go new file mode 100644 index 00000000000..ee319c45b66 --- /dev/null +++ b/adapters/nativery/params_test.go @@ -0,0 +1,55 @@ +package nativery + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +// This file actually intends to test static/bidder-params/appnexus.json +// +// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.appnexus + +// TestValidParams makes sure that the appnexus schema accepts all imp.ext fields which we intend to support. +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, validParam := range validParams { + if err := validator.Validate(openrtb_ext.BidderNativery, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected nativery params: %s", validParam) + } + } +} + +// TestInvalidParams makes sure that the appnexus schema rejects all the imp.ext fields we don't support. +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, invalidParam := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderNativery, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"widgetId":"1"}`, +} + +var invalidParams = []string{ + ``, + `null`, + `true`, + `5`, + `4.2`, + `[]`, + `{}`, + `{"placement_id":123}`, +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 87821fd0c75..7843e24a0b2 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -156,6 +156,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/mobilefuse" "github.com/prebid/prebid-server/v3/adapters/mobkoi" "github.com/prebid/prebid-server/v3/adapters/motorik" + "github.com/prebid/prebid-server/v3/adapters/nativery" "github.com/prebid/prebid-server/v3/adapters/nativo" "github.com/prebid/prebid-server/v3/adapters/nextmillennium" "github.com/prebid/prebid-server/v3/adapters/nobid" @@ -408,6 +409,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderMobileFuse: mobilefuse.Builder, openrtb_ext.BidderMobkoi: mobkoi.Builder, openrtb_ext.BidderMotorik: motorik.Builder, + openrtb_ext.BidderNativery: nativery.Builder, openrtb_ext.BidderNativo: nativo.Builder, openrtb_ext.BidderNextMillennium: nextmillennium.Builder, openrtb_ext.BidderNoBid: nobid.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 67cf8e7c15e..a4791d48219 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -174,6 +174,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderMobileFuse, BidderMobkoi, BidderMotorik, + BidderNativery, BidderNativo, BidderNextMillennium, BidderNoBid, @@ -530,6 +531,7 @@ const ( BidderMobileFuse BidderName = "mobilefuse" BidderMobkoi BidderName = "mobkoi" BidderMotorik BidderName = "motorik" + BidderNativery BidderName = "nativery" BidderNativo BidderName = "nativo" BidderNextMillennium BidderName = "nextmillennium" BidderNoBid BidderName = "nobid" diff --git a/openrtb_ext/imp_nativery.go b/openrtb_ext/imp_nativery.go new file mode 100644 index 00000000000..2094184a8e5 --- /dev/null +++ b/openrtb_ext/imp_nativery.go @@ -0,0 +1,8 @@ +package openrtb_ext + +// ImpExtNativery defines the contract for bidrequest.imp[i].ext.prebid.bidder.nativery +// ref to json schema in static/bidder-params/nativery + +type ImpExtNativery struct { + WidgetId string `json:"widgetId"` +} diff --git a/static/bidder-info/nativery.yaml b/static/bidder-info/nativery.yaml new file mode 100644 index 00000000000..f7511730b63 --- /dev/null +++ b/static/bidder-info/nativery.yaml @@ -0,0 +1,12 @@ +endpoint: "https://hb.nativery.com/openrtb2/auction" +openrtb: + version: 2.6 +maintainer: + email: "andrea.fassina@nativery.com" +gvlVendorID: 1133 +capabilities: + site: + mediaTypes: + - banner + - native + - video diff --git a/static/bidder-params/nativery.json b/static/bidder-params/nativery.json new file mode 100644 index 00000000000..f82eb58e8ab --- /dev/null +++ b/static/bidder-params/nativery.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Nativery Adapter Params", + "description": "A schema which validates params accepted by the Natiery adapter", + + "type": "object", + "properties": { + "widgetId": { + "type": "string", + "description": "An ID which identifies this Nativery widget" + } + }, + + "required": ["widgetId"] + } \ No newline at end of file From 00002587e4c962db3db7c58cf257f3881a3acd04 Mon Sep 17 00:00:00 2001 From: nicoladellamorte Date: Tue, 29 Apr 2025 12:36:37 +0200 Subject: [PATCH 2/9] test: addeed tests for multi imp and invalid datas --- .../multi-format-multi-imp-type.json | 393 ++++++++++++++++++ .../supplemental/invalid_bid_media_type.json | 120 ++++++ .../supplemental/invalid_imp_ext.json | 34 ++ .../supplemental/invalid_response.json | 86 ++++ 4 files changed, 633 insertions(+) create mode 100644 adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json create mode 100644 adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json create mode 100644 adapters/nativery/nativerytest/supplemental/invalid_imp_ext.json create mode 100644 adapters/nativery/nativerytest/supplemental/invalid_response.json diff --git a/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json b/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json new file mode 100644 index 00000000000..8447d731d0c --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json @@ -0,0 +1,393 @@ +{ + "mockBidRequest": { + "id": "test-multi-request-id", + "imp": [ + { + "id": "imp-banner", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": { "widgetId": "1" } + } + }, + { + "id": "imp-native", + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":25}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "bidder": { "widgetId": "1" } + } + }, + { + "id": "imp-hybrid", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "bidder": { "widgetId": "1" } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-multi-request-id", + "ext": { + "nativery": { "isAmp": false, "widgetId": "1" } + }, + "imp": [ + { + "id": "imp-banner", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["imp-banner"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multi-request-id", + "seatbid": [ + { + "seat": "nat-123", + "bid": [ + { + "id": "bid-banner", + "impid": "imp-banner", + "price": 800, + "adm": "
banner ad
", + "adomain": ["example.com"], + "cid": "cid-banner", + "crid": "crid-banner", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + } + ] + } + ], + "cur": "EUR" + } + } + }, + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-multi-request-id", + "ext": { + "nativery": { "isAmp": false, "widgetId": "1" } + }, + "imp": [ + { + "id": "imp-native", + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":25}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["imp-native"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multi-request-id", + "seatbid": [ + { + "seat": "nat-123", + "bid": [ + { + "id": "bid-native", + "impid": "imp-native", + "price": 600, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click\"}}}", + "adomain": ["example.com"], + "cid": "cid-native", + "crid": "crid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + } + ] + } + ], + "cur": "EUR" + } + } + }, + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-multi-request-id", + "ext": { + "nativery": { "isAmp": false, "widgetId": "1" } + }, + "imp": [ + { + "id": "imp-hybrid", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["imp-hybrid"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multi-request-id", + "seatbid": [ + { + "seat": "nat-123", + "bid": [ + { + "id": "bid-hybrid-banner", + "impid": "imp-hybrid", + "price": 1000, + "adm": "
hybrid banner
", + "adomain": ["example.com"], + "cid": "cid-hybrid-banner", + "crid": "crid-hybrid-banner", + "cat": ["IAB13-4"], + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + { + "id": "bid-hybrid-native", + "impid": "imp-hybrid", + "price": 500, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click2\"}}}", + "adomain": ["example.com"], + "cid": "cid-hybrid-native", + "crid": "crid-hybrid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + } + ] + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "bid-banner", + "impid": "imp-banner", + "price": 800, + "adm": "
banner ad
", + "adomain": ["example.com"], + "cid": "cid-banner", + "crid": "crid-banner", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + "type": "banner" + } + ] + }, + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "bid-native", + "impid": "imp-native", + "price": 600, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click\"}}}", + "adomain": ["example.com"], + "cid": "cid-native", + "crid": "crid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + }, + "type": "native" + } + ] + }, + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "bid-hybrid-banner", + "impid": "imp-hybrid", + "price": 1000, + "adm": "
hybrid banner
", + "adomain": ["example.com"], + "cid": "cid-hybrid-banner", + "crid": "crid-hybrid-banner", + "cat": ["IAB13-4"], + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-hybrid-native", + "impid": "imp-hybrid", + "price": 500, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click2\"}}}", + "adomain": ["example.com"], + "cid": "cid-hybrid-native", + "crid": "crid-hybrid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json b/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json new file mode 100644 index 00000000000..8096f0e7add --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json @@ -0,0 +1,120 @@ +{ + "mockBidRequest": { + "id": "err-unknown-type", + "imp": [ + { + "id": "imp-1", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "ua", + "h": 100, + "w": 200 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "impIDs": ["imp-1"], + "body": { + "id": "err-unknown-type", + "imp": [ + { + "id": "imp-1", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "nativery": { + "id": "1", + "xhr": 2, + "v": 3, + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + } + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "ua", + "h": 100, + "w": 200 + }, + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + } + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "err-unknown-type", + "seatbid": [ + { + "bid": [ + { + "id": "bid-1", + "impid": "imp-1", + "price": 1.23, + "adm": "
", + "adomain": ["example.com"], + "cid": "cid", + "crid": "crid", + "cat": ["IAB1"], + "w": 300, + "h": 250, + "mtype": 3, + "ext": { + "nativery": { + "bid_ad_media_type": "UNKNOWN_TYPE", + "adv_id": "1", + "brand_category_id": 1 + } + } + } + ] + } + ], + "cur": "EUR" + } + } + } + ], + "expectedRequestCount": 1, + "expectedMakeRequestsErrors": [], + "expectedMakeBidsErrors": [ + { + "value": "unrecognized bid_ad_media_type", + "comparison": "startswith" + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [] + } + ] +} diff --git a/adapters/nativery/nativerytest/supplemental/invalid_imp_ext.json b/adapters/nativery/nativerytest/supplemental/invalid_imp_ext.json new file mode 100644 index 00000000000..b55780f4fee --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/invalid_imp_ext.json @@ -0,0 +1,34 @@ +{ + "mockBidRequest": { + "id": "err-imp-ext", + "imp": [ + { + "id": "imp-1", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": "THIS_IS_NOT_VALID_JSON" + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "ua", + "h": 100, + "w": 200 + } + }, + "expectedRequestCount": 0, + "expectedMakeRequestsErrors": [ + { + "value": "expect { or n, but found", + "comparison": "startswith" + } + ], + "expectedMakeBidsErrors": [], + "expectedBidResponses": [] +} diff --git a/adapters/nativery/nativerytest/supplemental/invalid_response.json b/adapters/nativery/nativerytest/supplemental/invalid_response.json new file mode 100644 index 00000000000..c4b1b217c37 --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/invalid_response.json @@ -0,0 +1,86 @@ +{ + "mockBidRequest": { + "id": "err-invalid-resp", + "imp": [ + { + "id": "imp-1", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "ua", + "h": 100, + "w": 200 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "impIDs": ["imp-1"], + "body": { + "id": "err-invalid-resp", + "imp": [ + { + "id": "imp-1", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "nativery": { + "id": "1", + "xhr": 2, + "v": 3, + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + } + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "ua", + "h": 100, + "w": 200 + }, + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + } + } + }, + "mockResponse": { + "status": 200, + "body": "NOT A JSON!" + } + } + ], + "expectedRequestCount": 1, + "expectedMakeRequestsErrors": [], + "expectedMakeBidsErrors": [ + { + "value": "expect { or n, but found", + "comparison": "startswith" + } + ], + "expectedBidResponses": [] +} From 6c8c7f0225eb4b32d09fa407ce9c1be84a505fee Mon Sep 17 00:00:00 2001 From: nicoladellamorte Date: Tue, 29 Apr 2025 13:38:09 +0200 Subject: [PATCH 3/9] fix: fix nativery adapter after review --- adapters/nativery/nativery.go | 94 ++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go index cf1684aaef0..4370bbf93f9 100644 --- a/adapters/nativery/nativery.go +++ b/adapters/nativery/nativery.go @@ -1,7 +1,6 @@ package nativery import ( - "encoding/json" "errors" "fmt" "maps" @@ -12,6 +11,7 @@ import ( "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/metrics" "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" ) // Function used to builds a new instance of the Nativery adapter for the given bidder with the given config. @@ -42,9 +42,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E // attach body request for all the impressions validImps := []openrtb2.Imp{} for i, imp := range request.Imp { - reqCopy.Imp = []openrtb2.Imp{imp} + nativeryExt, err := buildNativeryExt(&imp) - nativeryExt, err := buildNativeryExt(&reqCopy.Imp[0]) if err != nil { errs = append(errs, err) continue @@ -55,6 +54,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E widgetId = nativeryExt.WidgetId } + reqCopy.Imp = []openrtb2.Imp{imp} + if err := buildRequest(reqCopy, nativeryExt); err != nil { errs = append(errs, err) continue @@ -79,7 +80,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E if err != nil { return nil, append(errs, err) } - // TODO: optimize it, we reiterate imp there and before adapterRequests, errors := splitRequests(reqCopy.Imp, &reqCopy, reqExt, reqExtNativery, a.endpoint) return adapterRequests, append(errs, errors...) @@ -87,12 +87,12 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E func buildNativeryExt(imp *openrtb2.Imp) (openrtb_ext.ImpExtNativery, error) { var bidderExt adapters.ExtImpBidder - if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { return openrtb_ext.ImpExtNativery{}, err } var nativeryExt openrtb_ext.ImpExtNativery - if err := json.Unmarshal(bidderExt.Bidder, &nativeryExt); err != nil { + if err := jsonutil.Unmarshal(bidderExt.Bidder, &nativeryExt); err != nil { return openrtb_ext.ImpExtNativery{}, err } @@ -103,16 +103,15 @@ func buildNativeryExt(imp *openrtb2.Imp) (openrtb_ext.ImpExtNativery, error) { func buildRequest(reqCopy openrtb2.BidRequest, reqExt openrtb_ext.ImpExtNativery) error { impExt := impExt{Nativery: nativeryExtReqBody{ - Id: reqExt.WidgetId, - Xhr: 2, - V: 3, - // TODO: Site is only for browser request, we have to handle if the req comes from app or dooh + Id: reqExt.WidgetId, + Xhr: 2, + V: 3, Ref: reqCopy.Site.Page, RefRef: refRef{Page: reqCopy.Site.Page, Ref: reqCopy.Site.Ref}, }} var err error - reqCopy.Imp[0].Ext, err = json.Marshal(&impExt) + reqCopy.Imp[0].Ext, err = jsonutil.Marshal(&impExt) return err } @@ -143,7 +142,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest // handle response var nativeryResponse openrtb2.BidResponse - if err := json.Unmarshal(response.Body, &nativeryResponse); err != nil { + if err := jsonutil.Unmarshal(response.Body, &nativeryResponse); err != nil { return nil, []error{err} } @@ -156,7 +155,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest // should be data sended from nativery server to partecipate to the auction var bidExt bidExt - if err := json.Unmarshal(bid.Ext, &bidExt); err != nil { + if err := jsonutil.Unmarshal(bid.Ext, &bidExt); err != nil { errs = append(errs, err) continue } @@ -220,64 +219,79 @@ func buildBidMeta(mediaType string, advDomain []string) *openrtb_ext.ExtBidPrebi return &openrtb_ext.ExtBidPrebidMeta{ MediaType: mediaType, AdvertiserDomains: advDomain, - /* - DChain: json.RawMessage{} , - Cosa include Dchain: - nodes: Un array di oggetti che rappresentano i diversi partecipanti alla catena di domanda. - complete: Un flag che indica se la catena di domanda è completa (1) o incompleta (0). - ver: La versione del modulo Dchain utilizzato. - */ } } -func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, requestExt map[string]json.RawMessage, requestExtNativery bidReqExtNativery, uri string) ([]*adapters.RequestData, []error) { +// splitRequests creates one HTTP request per Imp by deep-copying the original BidRequest +func splitRequests( + imps []openrtb2.Imp, + request *openrtb2.BidRequest, + requestExt map[string]jsonutil.RawMessage, + requestExtNativery bidReqExtNativery, + uri string, +) ([]*adapters.RequestData, []error) { var errs []error - resArr := make([]*adapters.RequestData, 0, 1) + // Pre-allocate slice to hold one RequestData per imp + resArr := make([]*adapters.RequestData, 0, len(imps)) + // Prepare standard headers for all requests headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") headers.Add("Accept", "application/json") - nativeryExtJson, err := json.Marshal(requestExtNativery) + // Marshal the nativery-specific extension once + nativeryExtJson, err := jsonutil.Marshal(requestExtNativery) if err != nil { errs = append(errs, err) } - requestExtClone := maps.Clone(requestExt) - requestExtClone["nativery"] = nativeryExtJson - - request.Ext, err = json.Marshal(requestExtClone) - if err != nil { - errs = append(errs, err) - } + // Make a shallow copy of the original request struct to use as a template + baseReq := *request for _, imp := range imps { - impsForReq := []openrtb2.Imp{imp} - request.Imp = impsForReq + // Clone the bidder-level ext map and inject the nativery JSON + extClone := maps.Clone(requestExt) + extClone["nativery"] = nativeryExtJson - reqJSON, err := json.Marshal(request) + // Start from the base request copy for this imp + reqCopy := baseReq + + // Marshal the cloned ext back into JSON bytes + reqCopy.Ext, err = jsonutil.Marshal(extClone) if err != nil { errs = append(errs, err) - return nil, errs + continue } + // Replace the Imp array with a single-element slice for this imp + reqCopy.Imp = []openrtb2.Imp{imp} + + // Serialize this per-imp request to JSON + reqJSON, err := jsonutil.Marshal(&reqCopy) + if err != nil { + errs = append(errs, err) + continue + } + + // Build the RequestData for this imp resArr = append(resArr, &adapters.RequestData{ Method: "POST", Uri: uri, Body: reqJSON, Headers: headers, - ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + ImpIDs: openrtb_ext.GetImpIDs(reqCopy.Imp), }) } + return resArr, errs } -func getRequestExt(ext json.RawMessage) (map[string]json.RawMessage, error) { - extMap := make(map[string]json.RawMessage) +func getRequestExt(ext jsonutil.RawMessage) (map[string]jsonutil.RawMessage, error) { + extMap := make(map[string]jsonutil.RawMessage) if len(ext) > 0 { - if err := json.Unmarshal(ext, &extMap); err != nil { + if err := jsonutil.Unmarshal(ext, &extMap); err != nil { return nil, err } } @@ -285,12 +299,12 @@ func getRequestExt(ext json.RawMessage) (map[string]json.RawMessage, error) { return extMap, nil } -func getNativeryExt(extMap map[string]json.RawMessage, isAMP int, widgetId string) (bidReqExtNativery, error) { +func getNativeryExt(extMap map[string]jsonutil.RawMessage, isAMP int, widgetId string) (bidReqExtNativery, error) { var nativeryExt bidReqExtNativery // if ext.nativery already exists return it if nativeryExtJson, exists := extMap["nativery"]; exists && len(nativeryExtJson) > 0 { - if err := json.Unmarshal(nativeryExtJson, &nativeryExt); err != nil { + if err := jsonutil.Unmarshal(nativeryExtJson, &nativeryExt); err != nil { return nativeryExt, err } } From 486257148924b57b0899013c7749d7fdef1ce4db Mon Sep 17 00:00:00 2001 From: andreafassina <127768714+andreafassina@users.noreply.github.com> Date: Tue, 10 Jun 2025 15:23:36 +0200 Subject: [PATCH 4/9] refactor: addressed suggested changes --- adapters/nativery/nativery.go | 48 +-- .../nativery/nativerytest/amp/banner.json | 189 +++++++++ .../amp/multi-format-multi-imp-type.json | 393 ++++++++++++++++++ .../nativery/nativerytest/amp/native.json | 179 ++++++++ adapters/nativery/nativerytest/amp/video.json | 187 +++++++++ .../exemplary/banner-no-currency.json | 188 +++++++++ .../exemplary/native-no-currency.json | 178 ++++++++ .../exemplary/video-no-currency.json | 186 +++++++++ static/bidder-info/nativery.yaml | 2 +- static/bidder-params/nativery.json | 2 +- 10 files changed, 1515 insertions(+), 37 deletions(-) create mode 100644 adapters/nativery/nativerytest/amp/banner.json create mode 100644 adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json create mode 100644 adapters/nativery/nativerytest/amp/native.json create mode 100644 adapters/nativery/nativerytest/amp/video.json create mode 100644 adapters/nativery/nativerytest/exemplary/banner-no-currency.json create mode 100644 adapters/nativery/nativerytest/exemplary/native-no-currency.json create mode 100644 adapters/nativery/nativerytest/exemplary/video-no-currency.json diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go index 4370bbf93f9..f01fab5ae0c 100644 --- a/adapters/nativery/nativery.go +++ b/adapters/nativery/nativery.go @@ -40,7 +40,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var widgetId string // attach body request for all the impressions - validImps := []openrtb2.Imp{} + validImps := make([]openrtb2.Imp, 0, len(request.Imp)) for i, imp := range request.Imp { nativeryExt, err := buildNativeryExt(&imp) @@ -55,14 +55,20 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } reqCopy.Imp = []openrtb2.Imp{imp} + reqCopy.Imp[0].Ext, err = jsonutil.Marshal(impExt{Nativery: nativeryExtReqBody{ + Id: nativeryExt.WidgetId, + Xhr: 2, + V: 3, + Ref: reqCopy.Site.Page, + RefRef: refRef{Page: reqCopy.Site.Page, Ref: reqCopy.Site.Ref}, + }}) - if err := buildRequest(reqCopy, nativeryExt); err != nil { + if err != nil { errs = append(errs, err) continue } - validImps = append(validImps, reqCopy.Imp...) - + validImps = append(validImps, reqCopy.Imp[0]) } reqCopy.Imp = validImps @@ -80,9 +86,9 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E if err != nil { return nil, append(errs, err) } - adapterRequests, errors := splitRequests(reqCopy.Imp, &reqCopy, reqExt, reqExtNativery, a.endpoint) + adapterRequests, splitErrors := splitRequests(reqCopy.Imp, &reqCopy, reqExt, reqExtNativery, a.endpoint) - return adapterRequests, append(errs, errors...) + return adapterRequests, append(errs, splitErrors...) } func buildNativeryExt(imp *openrtb2.Imp) (openrtb_ext.ImpExtNativery, error) { @@ -99,23 +105,6 @@ func buildNativeryExt(imp *openrtb2.Imp) (openrtb_ext.ImpExtNativery, error) { return nativeryExt, nil } -// utility function used to build the body for the http request for a single impression -func buildRequest(reqCopy openrtb2.BidRequest, reqExt openrtb_ext.ImpExtNativery) error { - - impExt := impExt{Nativery: nativeryExtReqBody{ - Id: reqExt.WidgetId, - Xhr: 2, - V: 3, - Ref: reqCopy.Site.Page, - RefRef: refRef{Page: reqCopy.Site.Page, Ref: reqCopy.Site.Ref}, - }} - - var err error - reqCopy.Imp[0].Ext, err = jsonutil.Marshal(&impExt) - - return err -} - // makebids handles the entire bidding process for a single BidRequest. // It creates and sends bid requests to multiple ad exchanges, receives // and parses responses, extracts bids and other relevant information, @@ -202,17 +191,6 @@ func getMediaTypeForBid(bid *bidExt) (openrtb_ext.BidType, error) { } } -func convertIntToBoolean(num *int) bool { - var b bool - // Dereferenzia num usando * - if num != nil && *num == 1 { - b = true - } else { - b = false - } - return b -} - func buildBidMeta(mediaType string, advDomain []string) *openrtb_ext.ExtBidPrebidMeta { //advertiserDomains and dchain are encouraged to implements @@ -309,7 +287,7 @@ func getNativeryExt(extMap map[string]jsonutil.RawMessage, isAMP int, widgetId s } } - nativeryExt.IsAMP = convertIntToBoolean(&isAMP) + nativeryExt.IsAMP = isAMP == 1 nativeryExt.WidgetId = widgetId return nativeryExt, nil diff --git a/adapters/nativery/nativerytest/amp/banner.json b/adapters/nativery/nativerytest/amp/banner.json new file mode 100644 index 00000000000..bf8622a144e --- /dev/null +++ b/adapters/nativery/nativerytest/amp/banner.json @@ -0,0 +1,189 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": true, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json b/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json new file mode 100644 index 00000000000..48600423bb5 --- /dev/null +++ b/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json @@ -0,0 +1,393 @@ +{ + "mockBidRequest": { + "id": "test-multi-request-id", + "imp": [ + { + "id": "imp-banner", + "banner": { + "format": [{ "w": 300, "h": 250 }] + }, + "ext": { + "bidder": { "widgetId": "1" } + } + }, + { + "id": "imp-native", + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":25}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "bidder": { "widgetId": "1" } + } + }, + { + "id": "imp-hybrid", + "banner": { + "format": [{ "w": 728, "h": 90 }] + }, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "bidder": { "widgetId": "1" } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-multi-request-id", + "ext": { + "nativery": { "isAmp": true, "widgetId": "1" } + }, + "imp": [ + { + "id": "imp-banner", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["imp-banner"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multi-request-id", + "seatbid": [ + { + "seat": "nat-123", + "bid": [ + { + "id": "bid-banner", + "impid": "imp-banner", + "price": 800, + "adm": "
banner ad
", + "adomain": ["example.com"], + "cid": "cid-banner", + "crid": "crid-banner", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + } + ] + } + ], + "cur": "EUR" + } + } + }, + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-multi-request-id", + "ext": { + "nativery": { "isAmp": true, "widgetId": "1" } + }, + "imp": [ + { + "id": "imp-native", + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":25}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["imp-native"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multi-request-id", + "seatbid": [ + { + "seat": "nat-123", + "bid": [ + { + "id": "bid-native", + "impid": "imp-native", + "price": 600, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click\"}}}", + "adomain": ["example.com"], + "cid": "cid-native", + "crid": "crid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + } + ] + } + ], + "cur": "EUR" + } + } + }, + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-multi-request-id", + "ext": { + "nativery": { "isAmp": true, "widgetId": "1" } + }, + "imp": [ + { + "id": "imp-hybrid", + "banner": { "format": [{ "w": 728, "h": 90 }] }, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200}}],\"context\":1,\"plcmttype\":1}" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["imp-hybrid"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multi-request-id", + "seatbid": [ + { + "seat": "nat-123", + "bid": [ + { + "id": "bid-hybrid-banner", + "impid": "imp-hybrid", + "price": 1000, + "adm": "
hybrid banner
", + "adomain": ["example.com"], + "cid": "cid-hybrid-banner", + "crid": "crid-hybrid-banner", + "cat": ["IAB13-4"], + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + { + "id": "bid-hybrid-native", + "impid": "imp-hybrid", + "price": 500, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click2\"}}}", + "adomain": ["example.com"], + "cid": "cid-hybrid-native", + "crid": "crid-hybrid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + } + ] + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "bid-banner", + "impid": "imp-banner", + "price": 800, + "adm": "
banner ad
", + "adomain": ["example.com"], + "cid": "cid-banner", + "crid": "crid-banner", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + "type": "banner" + } + ] + }, + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "bid-native", + "impid": "imp-native", + "price": 600, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click\"}}}", + "adomain": ["example.com"], + "cid": "cid-native", + "crid": "crid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + }, + "type": "native" + } + ] + }, + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "bid-hybrid-banner", + "impid": "imp-hybrid", + "price": 1000, + "adm": "
hybrid banner
", + "adomain": ["example.com"], + "cid": "cid-hybrid-banner", + "crid": "crid-hybrid-banner", + "cat": ["IAB13-4"], + "w": 728, + "h": 90, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-hybrid-native", + "impid": "imp-hybrid", + "price": 500, + "adm": "{\"native\":{\"assets\":[…],\"link\":{\"url\":\"http://example.com/click2\"}}}", + "adomain": ["example.com"], + "cid": "cid-hybrid-native", + "crid": "crid-hybrid-native", + "cat": ["IAB15-1"], + "mtype": 3, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native" + } + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/amp/native.json b/adapters/nativery/nativerytest/amp/native.json new file mode 100644 index 00000000000..4b014b9ed8c --- /dev/null +++ b/adapters/nativery/nativerytest/amp/native.json @@ -0,0 +1,179 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"context\":1,\"plcmttype\":1,\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"type\":3,\"w\":120,\"h\":100}},{\"id\":1,\"required\":1,\"title\":{\"len\":140}},{\"id\":2,\"data\":{\"type\":1}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": true, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"context\":1,\"plcmttype\":1,\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"type\":3,\"w\":120,\"h\":100}},{\"id\":1,\"required\":1,\"title\":{\"len\":140}},{\"id\":2,\"data\":{\"type\":1}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1]}]}", + "ver": "1.2" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":3,\"required\":1,\"img\":{\"url\":\"http://example.com/img/url\",\"w\":120,\"h\":100}},{\"id\":0,\"required\":1,\"title\":{\"text\":\"Test title\"}},{\"id\":5,\"data\":{\"value\":\"Test sponsor\"}}],\"link\":{\"url\":\"http://example.com/click/url\"},\"imptrackers\":[\"http://example.com/impression\"],\"jstracker\":\"\\u003cscript src=\\\"http://example.com/impression\\\"\\u003e\\u003c/script\\u003e\"}", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 4, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":3,\"required\":1,\"img\":{\"url\":\"http://example.com/img/url\",\"w\":120,\"h\":100}},{\"id\":0,\"required\":1,\"title\":{\"text\":\"Test title\"}},{\"id\":5,\"data\":{\"value\":\"Test sponsor\"}}],\"link\":{\"url\":\"http://example.com/click/url\"},\"imptrackers\":[\"http://example.com/impression\"],\"jstracker\":\"\\u003cscript src=\\\"http://example.com/impression\\\"\\u003e\\u003c/script\\u003e\"}", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 4, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/amp/video.json b/adapters/nativery/nativerytest/amp/video.json new file mode 100644 index 00000000000..14377c11c1c --- /dev/null +++ b/adapters/nativery/nativerytest/amp/video.json @@ -0,0 +1,187 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "minduration": 15, + "maxduration": 30, + "protocols": [2, 3, 5, 6, 7, 8], + "w": 940, + "h": 560 + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": true, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "minduration": 15, + "maxduration": 30, + "protocols": [2, 3, 5, 6, 7, 8], + "w": 940, + "h": 560 + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": " ...", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 2, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "video", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": " ...", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 2, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "video", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/exemplary/banner-no-currency.json b/adapters/nativery/nativerytest/exemplary/banner-no-currency.json new file mode 100644 index 00000000000..24b0e55afc7 --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/banner-no-currency.json @@ -0,0 +1,188 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/exemplary/native-no-currency.json b/adapters/nativery/nativerytest/exemplary/native-no-currency.json new file mode 100644 index 00000000000..4014595d2dc --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/native-no-currency.json @@ -0,0 +1,178 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"context\":1,\"plcmttype\":1,\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"type\":3,\"w\":120,\"h\":100}},{\"id\":1,\"required\":1,\"title\":{\"len\":140}},{\"id\":2,\"data\":{\"type\":1}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"context\":1,\"plcmttype\":1,\"assets\":[{\"id\":0,\"required\":1,\"img\":{\"type\":3,\"w\":120,\"h\":100}},{\"id\":1,\"required\":1,\"title\":{\"len\":140}},{\"id\":2,\"data\":{\"type\":1}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1]}]}", + "ver": "1.2" + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":3,\"required\":1,\"img\":{\"url\":\"http://example.com/img/url\",\"w\":120,\"h\":100}},{\"id\":0,\"required\":1,\"title\":{\"text\":\"Test title\"}},{\"id\":5,\"data\":{\"value\":\"Test sponsor\"}}],\"link\":{\"url\":\"http://example.com/click/url\"},\"imptrackers\":[\"http://example.com/impression\"],\"jstracker\":\"\\u003cscript src=\\\"http://example.com/impression\\\"\\u003e\\u003c/script\\u003e\"}", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 4, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":3,\"required\":1,\"img\":{\"url\":\"http://example.com/img/url\",\"w\":120,\"h\":100}},{\"id\":0,\"required\":1,\"title\":{\"text\":\"Test title\"}},{\"id\":5,\"data\":{\"value\":\"Test sponsor\"}}],\"link\":{\"url\":\"http://example.com/click/url\"},\"imptrackers\":[\"http://example.com/impression\"],\"jstracker\":\"\\u003cscript src=\\\"http://example.com/impression\\\"\\u003e\\u003c/script\\u003e\"}", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 4, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "native", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/nativery/nativerytest/exemplary/video-no-currency.json b/adapters/nativery/nativerytest/exemplary/video-no-currency.json new file mode 100644 index 00000000000..5badc459001 --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/video-no-currency.json @@ -0,0 +1,186 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "minduration": 15, + "maxduration": 30, + "protocols": [2, 3, 5, 6, 7, 8], + "w": 940, + "h": 560 + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": ["video/mp4"], + "minduration": 15, + "maxduration": 30, + "protocols": [2, 3, 5, 6, 7, 8], + "w": 940, + "h": 560 + }, + "ext": { + "nativery": { + "id": "1", + "ref": "http://example.com", + "refref": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "v": 3, + "xhr": 2 + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": " ...", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 2, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "video", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + } + ], + "seat": "nat-123" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "nurl": "http://example.com/win/1000", + "adm": " ...", + "adomain": ["example.com"], + "cid": "test-cid", + "crid": "test-crid", + "cat": ["IAB13-4"], + "mtype": 2, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "video", + "impression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpression": { + "url": "impressionUrl", + "options": { + "body": {}, + "method": "POST" + } + }, + "realImpressionAd": { + "url": "impressionAdUrl", + "options": { + "body": {}, + "method": "POST" + } + } + } + } + }, + "type": "video" + } + ] + } + ] +} diff --git a/static/bidder-info/nativery.yaml b/static/bidder-info/nativery.yaml index f7511730b63..47f05b7aaf9 100644 --- a/static/bidder-info/nativery.yaml +++ b/static/bidder-info/nativery.yaml @@ -2,7 +2,7 @@ endpoint: "https://hb.nativery.com/openrtb2/auction" openrtb: version: 2.6 maintainer: - email: "andrea.fassina@nativery.com" + email: "developer@nativery.com" gvlVendorID: 1133 capabilities: site: diff --git a/static/bidder-params/nativery.json b/static/bidder-params/nativery.json index f82eb58e8ab..f8d46933410 100644 --- a/static/bidder-params/nativery.json +++ b/static/bidder-params/nativery.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Nativery Adapter Params", - "description": "A schema which validates params accepted by the Natiery adapter", + "description": "A schema which validates params accepted by the Nativery adapter", "type": "object", "properties": { From 5c56fbc631813dadb8809ab7e12a47035de44757 Mon Sep 17 00:00:00 2001 From: Andrea Fassina Date: Wed, 11 Jun 2025 08:53:18 +0200 Subject: [PATCH 5/9] refactor: move structs to nativery.go --- adapters/nativery/models.go | 62 ---------------------------------- adapters/nativery/nativery.go | 63 +++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 62 deletions(-) delete mode 100644 adapters/nativery/models.go diff --git a/adapters/nativery/models.go b/adapters/nativery/models.go deleted file mode 100644 index cb3c6103534..00000000000 --- a/adapters/nativery/models.go +++ /dev/null @@ -1,62 +0,0 @@ -package nativery - -type adapter struct { - endpoint string -} - -type refRef struct { - Page string `json:"page"` - Ref string `json:"ref"` -} - -// request body to send to widget server in ext -type nativeryExtReqBody struct { - Id string `json:"id"` //the placement/widget id - Xhr int `json:"xhr"` - V int `json:"v"` - Ref string `json:"ref"` - RefRef refRef `json:"refref"` -} - -type impExt struct { - Nativery nativeryExtReqBody `json:"nativery"` -} - -type bidReqExtNativery struct { - IsAMP bool `json:"isAmp"` - WidgetId string `json:"widgetId"` -} - -type ImpressionBody struct { - WidgetId string `json:"idw"` - UrlId string `json:"idu"` - ImpressionId string `json:"idi"` - AdIds []string `json:"ida"` - IsAMP bool `json:"isAmp"` - Ref string `json:"ref"` - RefRef string `json:"refref"` - SessionId string `json:"sid"` -} - -type ImpressionOptions struct { - Method string `json:"method"` - Body ImpressionBody `json:"body"` -} -type ImpressionData struct { - Url string `json:"url"` - Options ImpressionOptions `json:"options"` -} -type bidExtNativery struct { - BidType string `json:"bid_ad_media_type"` - BidAdvDomains []string `json:"bid_adv_domains"` - - AdvertiserId string `json:"adv_id,omitempty"` - BrandCategory int `json:"brand_category_id,omitempty"` - Impression ImpressionData `json:"impression"` - RealImpression ImpressionData `json:"realImpression"` - RealImpressionAd ImpressionData `json:"realImpressionAd"` -} - -type bidExt struct { - Nativery bidExtNativery `json:"nativery"` -} diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go index f01fab5ae0c..dd1715e72b0 100644 --- a/adapters/nativery/nativery.go +++ b/adapters/nativery/nativery.go @@ -14,6 +14,69 @@ import ( "github.com/prebid/prebid-server/v3/util/jsonutil" ) +type adapter struct { + endpoint string +} + +type refRef struct { + Page string `json:"page"` + Ref string `json:"ref"` +} + +// request body to send to widget server in ext +type nativeryExtReqBody struct { + Id string `json:"id"` //the placement/widget id + Xhr int `json:"xhr"` + V int `json:"v"` + Ref string `json:"ref"` + RefRef refRef `json:"refref"` +} + +type impExt struct { + Nativery nativeryExtReqBody `json:"nativery"` +} + +type bidReqExtNativery struct { + IsAMP bool `json:"isAmp"` + WidgetId string `json:"widgetId"` +} + +type ImpressionBody struct { + WidgetId string `json:"idw"` + UrlId string `json:"idu"` + ImpressionId string `json:"idi"` + AdIds []string `json:"ida"` + IsAMP bool `json:"isAmp"` + Ref string `json:"ref"` + RefRef string `json:"refref"` + SessionId string `json:"sid"` +} + +type ImpressionOptions struct { + Method string `json:"method"` + Body ImpressionBody `json:"body"` +} + +type ImpressionData struct { + Url string `json:"url"` + Options ImpressionOptions `json:"options"` +} + +type bidExtNativery struct { + BidType string `json:"bid_ad_media_type"` + BidAdvDomains []string `json:"bid_adv_domains"` + + AdvertiserId string `json:"adv_id,omitempty"` + BrandCategory int `json:"brand_category_id,omitempty"` + Impression ImpressionData `json:"impression"` + RealImpression ImpressionData `json:"realImpression"` + RealImpressionAd ImpressionData `json:"realImpressionAd"` +} + +type bidExt struct { + Nativery bidExtNativery `json:"nativery"` +} + // Function used to builds a new instance of the Nativery adapter for the given bidder with the given config. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { // build bidder From f9bee0d57b47a6f1876bc9c85673495989684130 Mon Sep 17 00:00:00 2001 From: andreafassina <127768714+andreafassina@users.noreply.github.com> Date: Fri, 13 Jun 2025 11:25:21 +0200 Subject: [PATCH 6/9] test: add in-app test and remove no more used ext data --- adapters/nativery/nativery.go | 81 ++------- .../nativery/nativerytest/amp/banner.json | 57 +------ .../amp/multi-format-multi-imp-type.json | 33 +--- .../nativery/nativerytest/amp/native.json | 57 +------ adapters/nativery/nativerytest/amp/video.json | 57 +------ .../nativerytest/exemplary/banner-app.json | 154 ++++++++++++++++++ .../exemplary/banner-no-currency.json | 57 +------ .../nativerytest/exemplary/banner.json | 57 +------ .../multi-format-multi-imp-type.json | 33 +--- .../exemplary/native-no-currency.json | 57 +------ .../nativerytest/exemplary/native.json | 57 +------ .../exemplary/video-no-currency.json | 57 +------ .../nativerytest/exemplary/video.json | 57 +------ .../supplemental/invalid_bid_media_type.json | 11 +- .../supplemental/invalid_response.json | 11 +- .../nativerytest/supplemental/status_204.json | 11 +- .../nativerytest/supplemental/status_400.json | 11 +- 17 files changed, 223 insertions(+), 635 deletions(-) create mode 100644 adapters/nativery/nativerytest/exemplary/banner-app.json diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go index dd1715e72b0..3d699ccae87 100644 --- a/adapters/nativery/nativery.go +++ b/adapters/nativery/nativery.go @@ -1,7 +1,6 @@ package nativery import ( - "errors" "fmt" "maps" "net/http" @@ -9,6 +8,7 @@ import ( "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/metrics" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" @@ -18,59 +18,17 @@ type adapter struct { endpoint string } -type refRef struct { - Page string `json:"page"` - Ref string `json:"ref"` -} - -// request body to send to widget server in ext -type nativeryExtReqBody struct { - Id string `json:"id"` //the placement/widget id - Xhr int `json:"xhr"` - V int `json:"v"` - Ref string `json:"ref"` - RefRef refRef `json:"refref"` -} - -type impExt struct { - Nativery nativeryExtReqBody `json:"nativery"` -} - type bidReqExtNativery struct { IsAMP bool `json:"isAmp"` WidgetId string `json:"widgetId"` } -type ImpressionBody struct { - WidgetId string `json:"idw"` - UrlId string `json:"idu"` - ImpressionId string `json:"idi"` - AdIds []string `json:"ida"` - IsAMP bool `json:"isAmp"` - Ref string `json:"ref"` - RefRef string `json:"refref"` - SessionId string `json:"sid"` -} - -type ImpressionOptions struct { - Method string `json:"method"` - Body ImpressionBody `json:"body"` -} - -type ImpressionData struct { - Url string `json:"url"` - Options ImpressionOptions `json:"options"` -} - type bidExtNativery struct { BidType string `json:"bid_ad_media_type"` BidAdvDomains []string `json:"bid_adv_domains"` - AdvertiserId string `json:"adv_id,omitempty"` - BrandCategory int `json:"brand_category_id,omitempty"` - Impression ImpressionData `json:"impression"` - RealImpression ImpressionData `json:"realImpression"` - RealImpressionAd ImpressionData `json:"realImpressionAd"` + AdvertiserId string `json:"adv_id,omitempty"` + BrandCategory int `json:"brand_category_id,omitempty"` } type bidExt struct { @@ -117,21 +75,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E widgetId = nativeryExt.WidgetId } - reqCopy.Imp = []openrtb2.Imp{imp} - reqCopy.Imp[0].Ext, err = jsonutil.Marshal(impExt{Nativery: nativeryExtReqBody{ - Id: nativeryExt.WidgetId, - Xhr: 2, - V: 3, - Ref: reqCopy.Site.Page, - RefRef: refRef{Page: reqCopy.Site.Page, Ref: reqCopy.Site.Ref}, - }}) - - if err != nil { - errs = append(errs, err) - continue - } - - validImps = append(validImps, reqCopy.Imp[0]) + validImps = append(validImps, imp) } reqCopy.Imp = validImps @@ -176,15 +120,16 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest // check if the response has no content if adapters.IsResponseStatusCodeNoContent(response) { // Extract nativery no content reason if is present - reason := "" - if response.Headers != nil { - reason = response.Headers.Get("X-Nativery-Error") + nativeryError := response.Headers.Get("X-Nativery-Error") + if nativeryError != "" { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("Nativery Error: %s.", nativeryError), + }} } - if reason == "" { - reason = "No Content" - } - // Add the reason to errors - return nil, []error{errors.New(reason)} + + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("No Content"), + }} } // check if the response has errors diff --git a/adapters/nativery/nativerytest/amp/banner.json b/adapters/nativery/nativerytest/amp/banner.json index bf8622a144e..254655da040 100644 --- a/adapters/nativery/nativerytest/amp/banner.json +++ b/adapters/nativery/nativerytest/amp/banner.json @@ -53,15 +53,8 @@ ] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -101,28 +94,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "display", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "display" } } } @@ -156,28 +128,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "display", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "display" } } }, diff --git a/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json b/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json index 48600423bb5..55328243307 100644 --- a/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json +++ b/adapters/nativery/nativerytest/amp/multi-format-multi-imp-type.json @@ -57,15 +57,8 @@ "id": "imp-banner", "banner": { "format": [{ "w": 300, "h": 250 }] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -132,15 +125,8 @@ "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":25}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}}],\"context\":1,\"plcmttype\":1}" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -206,15 +192,8 @@ "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200}}],\"context\":1,\"plcmttype\":1}" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } diff --git a/adapters/nativery/nativerytest/amp/native.json b/adapters/nativery/nativerytest/amp/native.json index 4b014b9ed8c..7d5b86aee44 100644 --- a/adapters/nativery/nativerytest/amp/native.json +++ b/adapters/nativery/nativerytest/amp/native.json @@ -45,15 +45,8 @@ "ver": "1.2" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -92,28 +85,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "native", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "native" } } } @@ -146,28 +118,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "native", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "native" } } }, diff --git a/adapters/nativery/nativerytest/amp/video.json b/adapters/nativery/nativerytest/amp/video.json index 14377c11c1c..e988e3f1d71 100644 --- a/adapters/nativery/nativerytest/amp/video.json +++ b/adapters/nativery/nativerytest/amp/video.json @@ -53,15 +53,8 @@ "h": 560 }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -100,28 +93,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "video", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "video" } } } @@ -154,28 +126,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "video", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "video" } } }, diff --git a/adapters/nativery/nativerytest/exemplary/banner-app.json b/adapters/nativery/nativerytest/exemplary/banner-app.json new file mode 100644 index 00000000000..45dfe824b24 --- /dev/null +++ b/adapters/nativery/nativerytest/exemplary/banner-app.json @@ -0,0 +1,154 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "app": { + "bundle": "com.app.awesome", + "name": "Amesome App", + "domain": "awesomeapp.com", + "id": "1" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "app": { + "bundle": "com.app.awesome", + "name": "Amesome App", + "domain": "awesomeapp.com", + "id": "1" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": [ + "test-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": [ + "awesomeapp.com" + ], + "cid": "test-cid", + "crid": "test-crid", + "cat": [ + "IAB13-4" + ], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + } + ], + "seat": "nat-123" + } + ], + "cur": "EUR" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [ + { + "bid": { + "id": "test-request-id", + "impid": "test-imp-id", + "price": 1000, + "adm": "
ad
", + "adomain": [ + "awesomeapp.com" + ], + "cid": "test-cid", + "crid": "test-crid", + "cat": [ + "IAB13-4" + ], + "w": 300, + "h": 250, + "mtype": 1, + "ext": { + "nativery": { + "adv_id": "1", + "brand_category_id": 1, + "bid_ad_media_type": "display" + } + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/nativery/nativerytest/exemplary/banner-no-currency.json b/adapters/nativery/nativerytest/exemplary/banner-no-currency.json index 24b0e55afc7..974e3e3ad56 100644 --- a/adapters/nativery/nativerytest/exemplary/banner-no-currency.json +++ b/adapters/nativery/nativerytest/exemplary/banner-no-currency.json @@ -53,15 +53,8 @@ ] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -101,28 +94,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "display", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "display" } } } @@ -155,28 +127,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "display", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "display" } } }, diff --git a/adapters/nativery/nativerytest/exemplary/banner.json b/adapters/nativery/nativerytest/exemplary/banner.json index 582dcc9d075..8a59fe9a68c 100644 --- a/adapters/nativery/nativerytest/exemplary/banner.json +++ b/adapters/nativery/nativerytest/exemplary/banner.json @@ -53,15 +53,8 @@ ] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -101,28 +94,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "display", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "display" } } } @@ -156,28 +128,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "display", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "display" } } }, diff --git a/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json b/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json index 8447d731d0c..0fad5510dca 100644 --- a/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json +++ b/adapters/nativery/nativerytest/exemplary/multi-format-multi-imp-type.json @@ -57,15 +57,8 @@ "id": "imp-banner", "banner": { "format": [{ "w": 300, "h": 250 }] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -132,15 +125,8 @@ "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":25}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":100,\"hmin\":100}}],\"context\":1,\"plcmttype\":1}" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -206,15 +192,8 @@ "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":50}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200}}],\"context\":1,\"plcmttype\":1}" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } diff --git a/adapters/nativery/nativerytest/exemplary/native-no-currency.json b/adapters/nativery/nativerytest/exemplary/native-no-currency.json index 4014595d2dc..63a30c9c3e5 100644 --- a/adapters/nativery/nativerytest/exemplary/native-no-currency.json +++ b/adapters/nativery/nativerytest/exemplary/native-no-currency.json @@ -45,15 +45,8 @@ "ver": "1.2" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -92,28 +85,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "native", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "native" } } } @@ -145,28 +117,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "native", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "native" } } }, diff --git a/adapters/nativery/nativerytest/exemplary/native.json b/adapters/nativery/nativerytest/exemplary/native.json index 63359efa8ac..0ba6ef33178 100644 --- a/adapters/nativery/nativerytest/exemplary/native.json +++ b/adapters/nativery/nativerytest/exemplary/native.json @@ -45,15 +45,8 @@ "ver": "1.2" }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -92,28 +85,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "native", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "native" } } } @@ -146,28 +118,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "native", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "native" } } }, diff --git a/adapters/nativery/nativerytest/exemplary/video-no-currency.json b/adapters/nativery/nativerytest/exemplary/video-no-currency.json index 5badc459001..599937ba09d 100644 --- a/adapters/nativery/nativerytest/exemplary/video-no-currency.json +++ b/adapters/nativery/nativerytest/exemplary/video-no-currency.json @@ -53,15 +53,8 @@ "h": 560 }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -100,28 +93,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "video", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "video" } } } @@ -153,28 +125,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "video", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "video" } } }, diff --git a/adapters/nativery/nativerytest/exemplary/video.json b/adapters/nativery/nativerytest/exemplary/video.json index e0f9831aac2..61ed00e95b8 100644 --- a/adapters/nativery/nativerytest/exemplary/video.json +++ b/adapters/nativery/nativerytest/exemplary/video.json @@ -53,15 +53,8 @@ "h": 560 }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } @@ -100,28 +93,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "video", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "video" } } } @@ -154,28 +126,7 @@ "nativery": { "adv_id": "1", "brand_category_id": 1, - "bid_ad_media_type": "video", - "impression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpression": { - "url": "impressionUrl", - "options": { - "body": {}, - "method": "POST" - } - }, - "realImpressionAd": { - "url": "impressionAdUrl", - "options": { - "body": {}, - "method": "POST" - } - } + "bid_ad_media_type": "video" } } }, diff --git a/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json b/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json index 8096f0e7add..e3944109b1d 100644 --- a/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json +++ b/adapters/nativery/nativerytest/supplemental/invalid_bid_media_type.json @@ -38,15 +38,8 @@ "format": [{ "w": 300, "h": 250 }] }, "ext": { - "nativery": { - "id": "1", - "xhr": 2, - "v": 3, - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - } + "bidder": { + "widgetId": "1" } } } diff --git a/adapters/nativery/nativerytest/supplemental/invalid_response.json b/adapters/nativery/nativerytest/supplemental/invalid_response.json index c4b1b217c37..a29d799df82 100644 --- a/adapters/nativery/nativerytest/supplemental/invalid_response.json +++ b/adapters/nativery/nativerytest/supplemental/invalid_response.json @@ -38,15 +38,8 @@ "format": [{ "w": 300, "h": 250 }] }, "ext": { - "nativery": { - "id": "1", - "xhr": 2, - "v": 3, - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - } + "bidder": { + "widgetId": "1" } } } diff --git a/adapters/nativery/nativerytest/supplemental/status_204.json b/adapters/nativery/nativerytest/supplemental/status_204.json index 4a53616c0ef..f56b2832b06 100644 --- a/adapters/nativery/nativerytest/supplemental/status_204.json +++ b/adapters/nativery/nativerytest/supplemental/status_204.json @@ -53,15 +53,8 @@ ] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } diff --git a/adapters/nativery/nativerytest/supplemental/status_400.json b/adapters/nativery/nativerytest/supplemental/status_400.json index 5364f6e144c..f75a26a3ebc 100644 --- a/adapters/nativery/nativerytest/supplemental/status_400.json +++ b/adapters/nativery/nativerytest/supplemental/status_400.json @@ -53,15 +53,8 @@ ] }, "ext": { - "nativery": { - "id": "1", - "ref": "http://example.com", - "refref": { - "page": "http://example.com", - "ref": "http://example.com" - }, - "v": 3, - "xhr": 2 + "bidder": { + "widgetId": "1" } } } From ba0812fe2bba5b19ae5fdc035369ec19b380e9cd Mon Sep 17 00:00:00 2001 From: andreafassina <127768714+andreafassina@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:45:09 +0200 Subject: [PATCH 7/9] Update adapters/nativery/nativery.go Co-authored-by: linux019 --- adapters/nativery/nativery.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go index 3d699ccae87..29e4254e2ed 100644 --- a/adapters/nativery/nativery.go +++ b/adapters/nativery/nativery.go @@ -128,7 +128,7 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } return nil, []error{&errortypes.BadServerResponse{ - Message: fmt.Sprintf("No Content"), + Message: "No Content", }} } From dd9df0c49d52d58acf0fcc262e06bb1eeb4b8bd0 Mon Sep 17 00:00:00 2001 From: Nicola Della Morte <146722784+nicoladellamorte@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:10:23 +0200 Subject: [PATCH 8/9] test: add invalid imp and remove comments --- adapters/nativery/nativery.go | 35 ---------- .../supplemental/invalid_imp.json | 64 +++++++++++++++++++ adapters/nativery/params_test.go | 6 -- openrtb_ext/imp_nativery.go | 3 - 4 files changed, 64 insertions(+), 44 deletions(-) create mode 100644 adapters/nativery/nativerytest/supplemental/invalid_imp.json diff --git a/adapters/nativery/nativery.go b/adapters/nativery/nativery.go index 29e4254e2ed..1cd05aac121 100644 --- a/adapters/nativery/nativery.go +++ b/adapters/nativery/nativery.go @@ -35,19 +35,13 @@ type bidExt struct { Nativery bidExtNativery `json:"nativery"` } -// Function used to builds a new instance of the Nativery adapter for the given bidder with the given config. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { - // build bidder bidder := &adapter{ endpoint: config.Endpoint, } return bidder, nil } -// makeRequests creates HTTP requests for a given BidRequest and adapter configuration. -// It generates requests for each ad exchange targeted by the BidRequest, -// serializes the BidRequest into the request body, and sets the appropriate -// HTTP headers and other parameters. func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { reqCopy := *request var errs []error @@ -70,7 +64,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E continue } - // at the first impression set widgetId value if i == 0 { widgetId = nativeryExt.WidgetId } @@ -79,7 +72,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } reqCopy.Imp = validImps - // If all the requests were malformed, don't bother making a server call with no impressions. if len(reqCopy.Imp) == 0 { return nil, errs } @@ -112,14 +104,8 @@ func buildNativeryExt(imp *openrtb2.Imp) (openrtb_ext.ImpExtNativery, error) { return nativeryExt, nil } -// makebids handles the entire bidding process for a single BidRequest. -// It creates and sends bid requests to multiple ad exchanges, receives -// and parses responses, extracts bids and other relevant information, -// and populates a BidderResponse object with the aggregated information. func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { - // check if the response has no content if adapters.IsResponseStatusCodeNoContent(response) { - // Extract nativery no content reason if is present nativeryError := response.Headers.Get("X-Nativery-Error") if nativeryError != "" { return nil, []error{&errortypes.BadInput{ @@ -132,25 +118,21 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest }} } - // check if the response has errors if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { return nil, []error{err} } - // handle response var nativeryResponse openrtb2.BidResponse if err := jsonutil.Unmarshal(response.Body, &nativeryResponse); err != nil { return nil, []error{err} } var errs []error - // create bidder with impressions length capacity bidderResponse := adapters.NewBidderResponseWithBidsCapacity(len(internalRequest.Imp)) for _, sb := range nativeryResponse.SeatBid { for i := range sb.Bid { bid := sb.Bid[i] - // should be data sended from nativery server to partecipate to the auction var bidExt bidExt if err := jsonutil.Unmarshal(bid.Ext, &bidExt); err != nil { errs = append(errs, err) @@ -162,20 +144,17 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest errs = append(errs, err) continue } - // get metadata bidMeta := buildBidMeta(string(bidType), bidExt.Nativery.BidAdvDomains) bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{ Bid: &bid, BidType: bidType, - // metadata is encouraged BidMeta: bidMeta, }) } } - // set bidder currency, EUR by default if nativeryResponse.Cur != "" { bidderResponse.Currency = nativeryResponse.Cur } else { @@ -185,7 +164,6 @@ func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest } -// getMediaTypeForBid switch nativery type in bid type. func getMediaTypeForBid(bid *bidExt) (openrtb_ext.BidType, error) { switch bid.Nativery.BidType { case "native": @@ -201,14 +179,12 @@ func getMediaTypeForBid(bid *bidExt) (openrtb_ext.BidType, error) { func buildBidMeta(mediaType string, advDomain []string) *openrtb_ext.ExtBidPrebidMeta { - //advertiserDomains and dchain are encouraged to implements return &openrtb_ext.ExtBidPrebidMeta{ MediaType: mediaType, AdvertiserDomains: advDomain, } } -// splitRequests creates one HTTP request per Imp by deep-copying the original BidRequest func splitRequests( imps []openrtb2.Imp, request *openrtb2.BidRequest, @@ -218,49 +194,39 @@ func splitRequests( ) ([]*adapters.RequestData, []error) { var errs []error - // Pre-allocate slice to hold one RequestData per imp resArr := make([]*adapters.RequestData, 0, len(imps)) - // Prepare standard headers for all requests headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") headers.Add("Accept", "application/json") - // Marshal the nativery-specific extension once nativeryExtJson, err := jsonutil.Marshal(requestExtNativery) if err != nil { errs = append(errs, err) } - // Make a shallow copy of the original request struct to use as a template baseReq := *request for _, imp := range imps { - // Clone the bidder-level ext map and inject the nativery JSON extClone := maps.Clone(requestExt) extClone["nativery"] = nativeryExtJson - // Start from the base request copy for this imp reqCopy := baseReq - // Marshal the cloned ext back into JSON bytes reqCopy.Ext, err = jsonutil.Marshal(extClone) if err != nil { errs = append(errs, err) continue } - // Replace the Imp array with a single-element slice for this imp reqCopy.Imp = []openrtb2.Imp{imp} - // Serialize this per-imp request to JSON reqJSON, err := jsonutil.Marshal(&reqCopy) if err != nil { errs = append(errs, err) continue } - // Build the RequestData for this imp resArr = append(resArr, &adapters.RequestData{ Method: "POST", Uri: uri, @@ -288,7 +254,6 @@ func getRequestExt(ext jsonutil.RawMessage) (map[string]jsonutil.RawMessage, err func getNativeryExt(extMap map[string]jsonutil.RawMessage, isAMP int, widgetId string) (bidReqExtNativery, error) { var nativeryExt bidReqExtNativery - // if ext.nativery already exists return it if nativeryExtJson, exists := extMap["nativery"]; exists && len(nativeryExtJson) > 0 { if err := jsonutil.Unmarshal(nativeryExtJson, &nativeryExt); err != nil { return nativeryExt, err diff --git a/adapters/nativery/nativerytest/supplemental/invalid_imp.json b/adapters/nativery/nativerytest/supplemental/invalid_imp.json new file mode 100644 index 00000000000..622ace50aae --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/invalid_imp.json @@ -0,0 +1,64 @@ +{ + "mockBidRequest": { + "id": "err-imp-banner-nosize", + "imp": [ + { + "id": "bad-imp-1", + "banner": {}, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { "page": "http://example.com", "ref": "http://example.com" }, + "device": { "ua": "ua", "h": 100, "w": 200 } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "err-imp-banner-nosize", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "bad-imp-1", + "banner": {}, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { "ua": "ua", "h": 100, "w": 200 } + }, + "impIDs": ["bad-imp-1"] + }, + "mockResponse": { + "status": 400, + "body": {} + } + } + ], + "expectedRequestCount": 1, + "expectedMakeRequestsErrors": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/nativery/params_test.go b/adapters/nativery/params_test.go index ee319c45b66..557c3e0bb99 100644 --- a/adapters/nativery/params_test.go +++ b/adapters/nativery/params_test.go @@ -7,11 +7,6 @@ import ( "github.com/prebid/prebid-server/v3/openrtb_ext" ) -// This file actually intends to test static/bidder-params/appnexus.json -// -// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.appnexus - -// TestValidParams makes sure that the appnexus schema accepts all imp.ext fields which we intend to support. func TestValidParams(t *testing.T) { validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") if err != nil { @@ -25,7 +20,6 @@ func TestValidParams(t *testing.T) { } } -// TestInvalidParams makes sure that the appnexus schema rejects all the imp.ext fields we don't support. func TestInvalidParams(t *testing.T) { validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") if err != nil { diff --git a/openrtb_ext/imp_nativery.go b/openrtb_ext/imp_nativery.go index 2094184a8e5..d63cf1e609c 100644 --- a/openrtb_ext/imp_nativery.go +++ b/openrtb_ext/imp_nativery.go @@ -1,8 +1,5 @@ package openrtb_ext -// ImpExtNativery defines the contract for bidrequest.imp[i].ext.prebid.bidder.nativery -// ref to json schema in static/bidder-params/nativery - type ImpExtNativery struct { WidgetId string `json:"widgetId"` } From fded54c3bff7f8e7d84e2801d49cbdf245eb2d79 Mon Sep 17 00:00:00 2001 From: Nicola Della Morte <146722784+nicoladellamorte@users.noreply.github.com> Date: Wed, 10 Sep 2025 16:21:08 +0200 Subject: [PATCH 9/9] test: increase test coverage (#8) --- .../supplemental/bad_bid_response.json | 74 ++++++++++++++++ .../supplemental/invalid_widget_id.json | 29 ++++++ .../supplemental/missing_widget_id.json | 57 ++++++++++++ .../status_204_nativery_error.json | 88 +++++++++++++++++++ 4 files changed, 248 insertions(+) create mode 100644 adapters/nativery/nativerytest/supplemental/bad_bid_response.json create mode 100644 adapters/nativery/nativerytest/supplemental/invalid_widget_id.json create mode 100644 adapters/nativery/nativerytest/supplemental/missing_widget_id.json create mode 100644 adapters/nativery/nativerytest/supplemental/status_204_nativery_error.json diff --git a/adapters/nativery/nativerytest/supplemental/bad_bid_response.json b/adapters/nativery/nativerytest/supplemental/bad_bid_response.json new file mode 100644 index 00000000000..6003e6e82ed --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/bad_bid_response.json @@ -0,0 +1,74 @@ +{ + "mockBidRequest": { + "id": "bad-bid-ext", + "imp": [ + { + "id": "1", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { "bidder": { "widgetId": "123" } } + } + ], + "site": { "page": "http://example.com", "ref": "http://example.com" }, + "device": { "ua": "ua", "h": 100, "w": 200 } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "http://example.com/hb", + "body": { + "id": "bad-bid-ext", + "imp": [ + { + "id": "1", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { "bidder": { "widgetId": "123" } } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { "ua": "ua", "h": 100, "w": 200 }, + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "123" + } + } + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "r", + "seatbid": [ + { + "bid": [ + { + "id": "b1", + "impid": "1", + "price": 1.2, + "adm": "
", + "ext": 123 + } + ] + } + ] + } + } + } + ], + "expectedRequestCount": 1, + "expectedMakeRequestsErrors": [], + "expectedMakeBidsErrors": [ + { "value": "expect { or n, but found", "comparison": "startswith" } + ], + "expectedBidResponses": [ + { + "currency": "EUR", + "bids": [] + } + ] +} diff --git a/adapters/nativery/nativerytest/supplemental/invalid_widget_id.json b/adapters/nativery/nativerytest/supplemental/invalid_widget_id.json new file mode 100644 index 00000000000..1d08bb40b62 --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/invalid_widget_id.json @@ -0,0 +1,29 @@ +{ + "mockBidRequest": { + "id": "err-nativeryext-widgetid-number", + "imp": [ + { + "id": "1", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { "bidder": { "widgetId": "1" } } + } + ], + "site": { "page": "http://example.com", "ref": "http://example.com" }, + "device": { "ua": "ua", "h": 100, "w": 200 }, + "ext": { + "nativery": { + "isAmp": false, + "widgetId": 123 + } + } + }, + "expectedRequestCount": 0, + "expectedMakeRequestsErrors": [ + { + "comparison": "regex", + "value": ".*cannot unmarshal nativery.*WidgetId.*" + } + ], + "expectedMakeBidsErrors": [], + "expectedBidResponses": [] +} diff --git a/adapters/nativery/nativerytest/supplemental/missing_widget_id.json b/adapters/nativery/nativerytest/supplemental/missing_widget_id.json new file mode 100644 index 00000000000..324cce094e8 --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/missing_widget_id.json @@ -0,0 +1,57 @@ +{ + "mockBidRequest": { + "id": "missing-widgetid-400", + "imp": [ + { + "id": "1", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { "bidder": {} } + } + ], + "site": { "page": "http://example.com", "ref": "http://example.com" }, + "device": { "ua": "ua", "h": 100, "w": 200 } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "http://example.com/hb", + "body": { + "id": "missing-widgetid-400", + "imp": [ + { + "id": "1", + "banner": { "format": [{ "w": 300, "h": 250 }] }, + "ext": { "bidder": {} } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { "ua": "ua", "h": 100, "w": 200 }, + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "" + } + } + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 400, + "body": "" + } + } + ], + "expectedRequestCount": 1, + "expectedMakeRequestsErrors": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400", + "comparison": "startswith" + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/nativery/nativerytest/supplemental/status_204_nativery_error.json b/adapters/nativery/nativerytest/supplemental/status_204_nativery_error.json new file mode 100644 index 00000000000..8cec9dda357 --- /dev/null +++ b/adapters/nativery/nativerytest/supplemental/status_204_nativery_error.json @@ -0,0 +1,88 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com/hb", + "body": { + "id": "test-request-id", + "ext": { + "nativery": { + "isAmp": false, + "widgetId": "1" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "widgetId": "1" + } + } + } + ], + "site": { + "page": "http://example.com", + "ref": "http://example.com" + }, + "device": { + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "h": 500, + "w": 1000 + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 204, + "body": {}, + "headers": { "X-Nativery-Error": ["some error"] }, + "error": ["No Content"] + } + } + ], + + "expectedBidResponses": [], + + "expectedMakeBidsErrors": [ + { "value": "Nativery Error: some error.", "comparison": "startswith" } + ] +}