From e9553ab3f3a9d4d03b8cf394aa7ac9c039fe845e Mon Sep 17 00:00:00 2001 From: Sander Date: Thu, 28 May 2020 17:21:20 +0200 Subject: [PATCH] Introduce Adhese adapter (#1292) Co-authored-by: Mateusz --- adapters/adhese/adhese.go | 269 ++++++++++++++++++ adapters/adhese/adhese_test.go | 11 + .../adhesetest/exemplary/banner-internal.json | 103 +++++++ .../adhesetest/exemplary/banner-market.json | 100 +++++++ .../exemplary/banner-video-internal.json | 103 +++++++ .../adhese/adhesetest/exemplary/video.json | 80 ++++++ .../req-invalid-empty-imp-ext.json | 38 +++ .../supplemental/req-invalid-empty-imp.json | 25 ++ .../supplemental/req-invalid-no-imp-ext.json | 37 +++ .../supplemental/res-invalid-height.json | 91 ++++++ .../supplemental/res-invalid-no-body.json | 62 ++++ .../supplemental/res-invalid-no-origin.json | 80 ++++++ .../supplemental/res-invalid-price.json | 91 ++++++ .../res-invalid-status-not-ok.json | 81 ++++++ .../supplemental/res-invalid-width.json | 91 ++++++ .../adhesetest/supplemental/res-no_bids.json | 54 ++++ .../res-no_impression_counter.json | 103 +++++++ adapters/adhese/params_test.go | 58 ++++ adapters/adhese/utils.go | 45 +++ config/config.go | 4 +- exchange/adapter_map.go | 2 + macros/macros.go | 1 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_adhese.go | 12 + static/bidder-info/adhese.yaml | 11 + static/bidder-params/adhese.json | 25 ++ usersync/usersyncers/syncer_test.go | 1 + 27 files changed, 1579 insertions(+), 1 deletion(-) create mode 100644 adapters/adhese/adhese.go create mode 100644 adapters/adhese/adhese_test.go create mode 100644 adapters/adhese/adhesetest/exemplary/banner-internal.json create mode 100644 adapters/adhese/adhesetest/exemplary/banner-market.json create mode 100644 adapters/adhese/adhesetest/exemplary/banner-video-internal.json create mode 100644 adapters/adhese/adhesetest/exemplary/video.json create mode 100644 adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp-ext.json create mode 100644 adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp.json create mode 100644 adapters/adhese/adhesetest/supplemental/req-invalid-no-imp-ext.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-invalid-height.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-invalid-no-body.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-invalid-no-origin.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-invalid-price.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-invalid-status-not-ok.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-invalid-width.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-no_bids.json create mode 100644 adapters/adhese/adhesetest/supplemental/res-no_impression_counter.json create mode 100644 adapters/adhese/params_test.go create mode 100644 adapters/adhese/utils.go create mode 100644 openrtb_ext/imp_adhese.go create mode 100644 static/bidder-info/adhese.yaml create mode 100644 static/bidder-params/adhese.json diff --git a/adapters/adhese/adhese.go b/adapters/adhese/adhese.go new file mode 100644 index 00000000000..10aaf6e820d --- /dev/null +++ b/adapters/adhese/adhese.go @@ -0,0 +1,269 @@ +package adhese + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "text/template" + + "github.com/golang/glog" + "github.com/mxmCherry/openrtb" + "github.com/prebid/prebid-server/adapters" + "github.com/prebid/prebid-server/errortypes" + "github.com/prebid/prebid-server/macros" + "github.com/prebid/prebid-server/openrtb_ext" +) + +type AdheseAdapter struct { + endpointTemplate template.Template +} + +func extractSlotParameter(parameters openrtb_ext.ExtImpAdhese) string { + return fmt.Sprintf("/sl%s-%s", url.PathEscape(parameters.Location), url.PathEscape(parameters.Format)) +} + +func extractTargetParameters(parameters openrtb_ext.ExtImpAdhese) string { + if len(parameters.Keywords) == 0 { + return "" + } + var parametersAsString = "" + var targetParsed map[string]interface{} + err := json.Unmarshal(parameters.Keywords, &targetParsed) + if err != nil { + return "" + } + + targetKeys := make([]string, 0, len(targetParsed)) + for key := range targetParsed { + targetKeys = append(targetKeys, key) + } + sort.Strings(targetKeys) + + for _, targetKey := range targetKeys { + var targetingValues = targetParsed[targetKey].([]interface{}) + parametersAsString += "/" + url.PathEscape(targetKey) + for _, targetRawValKey := range targetingValues { + var targetValueParsed = targetRawValKey.(string) + parametersAsString += targetValueParsed + ";" + } + parametersAsString = strings.TrimRight(parametersAsString, ";") + } + + return parametersAsString +} + +func extractGdprParameter(request *openrtb.BidRequest) string { + if request.User != nil { + var extUser openrtb_ext.ExtUser + if err := json.Unmarshal(request.User.Ext, &extUser); err == nil { + return "/xt" + extUser.Consent + } + } + return "" +} + +func extractRefererParameter(request *openrtb.BidRequest) string { + if request.Site != nil && request.Site.Page != "" { + return "/xf" + url.QueryEscape(request.Site.Page) + } + return "" +} + +func (a *AdheseAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + errs := make([]error, 0, len(request.Imp)) + + var err error + + // If all the requests are invalid, Call to adaptor is skipped + if len(request.Imp) == 0 { + errs = append(errs, WrapReqError("Imp is empty")) + return nil, errs + } + + var imp = &request.Imp[0] + var bidderExt adapters.ExtImpBidder + + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + errs = append(errs, WrapReqError("Request could not be parsed as ExtImpBidder due to: "+err.Error())) + return nil, errs + } + + var params openrtb_ext.ExtImpAdhese + if err := json.Unmarshal(bidderExt.Bidder, ¶ms); err != nil { + errs = append(errs, WrapReqError("Request could not be parsed as ExtImpAdhese due to: "+err.Error())) + return nil, errs + } + + // Compose url + endpointParams := macros.EndpointTemplateParams{AccountID: params.Account} + + host, err := macros.ResolveMacros(*&a.endpointTemplate, endpointParams) + if err != nil { + errs = append(errs, WrapReqError("Could not compose url from template and request account val: "+err.Error())) + return nil, errs + } + complete_url := fmt.Sprintf("%s%s%s%s%s", + host, + extractSlotParameter(params), + extractTargetParameters(params), + extractGdprParameter(request), + extractRefererParameter(request)) + + return []*adapters.RequestData{{ + Method: "GET", + Uri: complete_url, + }}, errs +} + +func (a *AdheseAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if response.StatusCode == http.StatusNoContent { + return nil, nil + } else if response.StatusCode != http.StatusOK { + return nil, []error{WrapServerError(fmt.Sprintf("Unexpected status code: %d.", response.StatusCode))} + } + + var bidResponse openrtb.BidResponse + + var adheseBidResponseArray []AdheseBid + if err := json.Unmarshal(response.Body, &adheseBidResponseArray); err != nil { + return nil, []error{err, WrapServerError(fmt.Sprintf("Response %v could not be parsed as generic Adhese bid.", string(response.Body)))} + } + + var adheseBid = adheseBidResponseArray[0] + + if adheseBid.Origin == "JERLICIA" { + var extArray []AdheseExt + var originDataArray []AdheseOriginData + if err := json.Unmarshal(response.Body, &extArray); err != nil { + return nil, []error{err, WrapServerError(fmt.Sprintf("Response %v could not be parsed to JERLICIA ext.", string(response.Body)))} + } + + if err := json.Unmarshal(response.Body, &originDataArray); err != nil { + return nil, []error{err, WrapServerError(fmt.Sprintf("Response %v could not be parsed to JERLICIA origin data.", string(response.Body)))} + } + bidResponse = convertAdheseBid(adheseBid, extArray[0], originDataArray[0]) + } else { + bidResponse = convertAdheseOpenRtbBid(adheseBid) + } + + price, err := strconv.ParseFloat(adheseBid.Extension.Prebid.Cpm.Amount, 64) + if err != nil { + return nil, []error{err, WrapServerError(fmt.Sprintf("Could not parse Price %v as float ", string(adheseBid.Extension.Prebid.Cpm.Amount)))} + } + width, err := strconv.ParseUint(adheseBid.Width, 10, 64) + if err != nil { + return nil, []error{err, WrapServerError(fmt.Sprintf("Could not parse Width %v as int ", string(adheseBid.Width)))} + } + height, err := strconv.ParseUint(adheseBid.Height, 10, 64) + if err != nil { + return nil, []error{err, WrapServerError(fmt.Sprintf("Could not parse Height %v as int ", string(adheseBid.Height)))} + } + bidResponse.Cur = adheseBid.Extension.Prebid.Cpm.Currency + if len(bidResponse.SeatBid) > 0 && len(bidResponse.SeatBid[0].Bid) > 0 { + bidResponse.SeatBid[0].Bid[0].Price = price + bidResponse.SeatBid[0].Bid[0].W = width + bidResponse.SeatBid[0].Bid[0].H = height + } + + bidderResponse := adapters.NewBidderResponseWithBidsCapacity(5) + + if len(bidResponse.SeatBid) == 0 { + return nil, []error{WrapServerError("Response resulted in an empty seatBid array.")} + } + + var errs []error + for _, sb := range bidResponse.SeatBid { + for i := 0; i < len(sb.Bid); i++ { + bid := sb.Bid[i] + bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{ + Bid: &bid, + BidType: getBidType(bid.AdM), + }) + + } + } + return bidderResponse, errs +} + +func convertAdheseBid(adheseBid AdheseBid, adheseExt AdheseExt, adheseOriginData AdheseOriginData) openrtb.BidResponse { + adheseExtJson, err := json.Marshal(adheseOriginData) + if err != nil { + glog.Error(fmt.Sprintf("Unable to parse adhese Origin Data as JSON due to %v", err)) + adheseExtJson = make([]byte, 0) + } + return openrtb.BidResponse{ + ID: adheseExt.Id, + SeatBid: []openrtb.SeatBid{{ + Bid: []openrtb.Bid{{ + DealID: adheseExt.OrderId, + CrID: adheseExt.Id, + AdM: getAdMarkup(adheseBid, adheseExt), + Ext: adheseExtJson, + }}, + Seat: "", + }}, + } +} + +func convertAdheseOpenRtbBid(adheseBid AdheseBid) openrtb.BidResponse { + var response openrtb.BidResponse = adheseBid.OriginData + if len(response.SeatBid) > 0 && len(response.SeatBid[0].Bid) > 0 { + response.SeatBid[0].Bid[0].AdM = adheseBid.Body + } + return response +} + +func getAdMarkup(adheseBid AdheseBid, adheseExt AdheseExt) string { + if adheseExt.Ext == "js" { + if ContainsAny(adheseBid.Body, []string{" 0 { + counter = "" + } + return adheseBid.Body + counter + } + if ContainsAny(adheseBid.Body, []string{"", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "1", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "
", + "w": 728, + "h": 90, + "id": "", + "impid": "", + "price": 1.000000, + "dealid": "888", + "crid": "60613369", + "ext": { + "adFormat": "", + "adType": "leaderboard", + "adspaceId": "", + "libId": "", + "orderProperty": "", + "priority": "", + "viewableImpressionCounter": "" + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/exemplary/banner-market.json b/adapters/adhese/adhesetest/exemplary/banner-market.json new file mode 100644 index 00000000000..340e6d87223 --- /dev/null +++ b/adapters/adhese/adhesetest/exemplary/banner-market.json @@ -0,0 +1,100 @@ +{ + "mockBidRequest": { + "id": "test-req", + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "market", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + }, + "page": "dummy" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-market.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xfdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "APPNEXUS", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "originData": { + "seatbid": [ + { + "bid": [ + { + "crid": "60613369", + "dealid": null + } + ], + "seat": "958" + } + ] + }, + "width": "728", + "height": "90", + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "1", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "
", + "w": 728, + "h": 90, + "id": "", + "impid": "", + "crid": "60613369", + "price": 1.000000 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/exemplary/banner-video-internal.json b/adapters/adhese/adhesetest/exemplary/banner-video-internal.json new file mode 100644 index 00000000000..bd9203c2509 --- /dev/null +++ b/adapters/adhese/adhesetest/exemplary/banner-video-internal.json @@ -0,0 +1,103 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "JERLICIA", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "orderId": "888", + "id": "60613369", + "width": "728", + "height": "90", + "body": "dummy", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "1", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "dummy", + "w": 728, + "h": 90, + "id": "", + "impid": "", + "price": 1.000000, + "dealid": "888", + "crid": "60613369", + "ext": { + "adFormat": "", + "adType": "leaderboard", + "adspaceId": "", + "libId": "", + "orderProperty": "", + "priority": "", + "viewableImpressionCounter": "" + } + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/exemplary/video.json b/adapters/adhese/adhesetest/exemplary/video.json new file mode 100644 index 00000000000..134e3add52d --- /dev/null +++ b/adapters/adhese/adhesetest/exemplary/video.json @@ -0,0 +1,80 @@ +{ + "mockBidRequest": { + "imp": [{ + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + }] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "RUBICON", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "originData": { + "seatbid": [ + { + "bid": [ + { + "crid": "60613369", + "dealid": null + } + ], + "seat": "958" + } + ] + }, + "width": "640", + "height": "350", + "body": "", + "extension": { + "prebid": { + "cpm": { + "amount": "2.1", + "currency": "USD" + } + } + } + }] + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "", + "w": 640, + "h": 350, + "id": "", + "impid": "", + "crid": "60613369", + "price": 2.1 + }, + "type": "video" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp-ext.json b/adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp-ext.json new file mode 100644 index 00000000000..e98823b2914 --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp-ext.json @@ -0,0 +1,38 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": {} + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "Request could not be parsed as ExtImpAdhese due to: unexpected end of JSON input", + "comparison": "literal" + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp.json b/adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp.json new file mode 100644 index 00000000000..a4fc8230e1e --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/req-invalid-empty-imp.json @@ -0,0 +1,25 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "Imp is empty", + "comparison": "literal" + } + ] + } \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/req-invalid-no-imp-ext.json b/adapters/adhese/adhesetest/supplemental/req-invalid-no-imp-ext.json new file mode 100644 index 00000000000..bcb891719ae --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/req-invalid-no-imp-ext.json @@ -0,0 +1,37 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "Request could not be parsed as ExtImpBidder due to: unexpected end of JSON input", + "comparison": "literal" + } + ] + } \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-invalid-height.json b/adapters/adhese/adhesetest/supplemental/res-invalid-height.json new file mode 100644 index 00000000000..1e11df2f4c4 --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-invalid-height.json @@ -0,0 +1,91 @@ +{ + "mockBidRequest": { + "id": "test-req", + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "market", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + }, + "page": "dummy" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-market.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xfdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "APPNEXUS", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "originData": { + "seatbid": [ + { + "bid": [ + { + "crid": "60613369", + "dealid": null + } + ], + "seat": "958" + } + ] + }, + "width": "728", + "height": 90, + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "10", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "json: cannot unmarshal number into Go struct field AdheseBid.height of type string", + "comparison": "literal" + }, { + "value": "Response (.*\n.*)+ could not be parsed as generic Adhese bid", + "comparison": "regex" + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-invalid-no-body.json b/adapters/adhese/adhesetest/supplemental/res-invalid-no-body.json new file mode 100644 index 00000000000..f970476450f --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-invalid-no-body.json @@ -0,0 +1,62 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy" + }, + "mockResponse": { + "status": 200 + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "unexpected end of JSON input", + "comparison": "literal" + },{ + "value": "Response could not be parsed as generic Adhese bid.", + "comparison": "literal" + } + ] + } \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-invalid-no-origin.json b/adapters/adhese/adhesetest/supplemental/res-invalid-no-origin.json new file mode 100644 index 00000000000..636e30741bb --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-invalid-no-origin.json @@ -0,0 +1,80 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "orderId": "888", + "id": "60613369", + "width": "728", + "height": "90", + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "1", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Response resulted in an empty seatBid array.", + "comparison": "literal" + } + ] + } \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-invalid-price.json b/adapters/adhese/adhesetest/supplemental/res-invalid-price.json new file mode 100644 index 00000000000..f23bf0f7cb1 --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-invalid-price.json @@ -0,0 +1,91 @@ +{ + "mockBidRequest": { + "id": "test-req", + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "market", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + }, + "page": "dummy" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-market.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xfdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "APPNEXUS", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "originData": { + "seatbid": [ + { + "bid": [ + { + "crid": "60613369", + "dealid": null + } + ], + "seat": "958" + } + ] + }, + "width": "728", + "height": "90", + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": 10, + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "json: cannot unmarshal number into Go struct field CPMValues.*\\.amount of type string", + "comparison": "regex" + }, { + "value": "Response (.*\n.*)+ could not be parsed as generic Adhese bid", + "comparison": "regex" + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-invalid-status-not-ok.json b/adapters/adhese/adhesetest/supplemental/res-invalid-status-not-ok.json new file mode 100644 index 00000000000..96f17b15b32 --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-invalid-status-not-ok.json @@ -0,0 +1,81 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy" + }, + "mockResponse": { + "status": 501, + "body": [{ + "origin": "JERLICIA", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "orderId": "888", + "id": "60613369", + "width": "728", + "height": "90", + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "1", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 501.", + "comparison": "literal" + } + ] + } \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-invalid-width.json b/adapters/adhese/adhesetest/supplemental/res-invalid-width.json new file mode 100644 index 00000000000..77b23d347af --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-invalid-width.json @@ -0,0 +1,91 @@ +{ + "mockBidRequest": { + "id": "test-req", + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "market", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + }, + "page": "dummy" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-market.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xfdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "APPNEXUS", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "originData": { + "seatbid": [ + { + "bid": [ + { + "crid": "60613369", + "dealid": null + } + ], + "seat": "958" + } + ] + }, + "width": 728, + "height": "90", + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "extension": { + "prebid": { + "cpm": { + "amount": "10", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "json: cannot unmarshal number into Go struct field AdheseBid.width of type string", + "comparison": "literal" + }, { + "value": "Response (.*\n.*)+ could not be parsed as generic Adhese bid", + "comparison": "regex" + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-no_bids.json b/adapters/adhese/adhesetest/supplemental/res-no_bids.json new file mode 100644 index 00000000000..c9630049f02 --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-no_bids.json @@ -0,0 +1,54 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy" + }, + "mockResponse": { + "status": 204, + "body": [] + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/adhese/adhesetest/supplemental/res-no_impression_counter.json b/adapters/adhese/adhesetest/supplemental/res-no_impression_counter.json new file mode 100644 index 00000000000..99af5671f4b --- /dev/null +++ b/adapters/adhese/adhesetest/supplemental/res-no_impression_counter.json @@ -0,0 +1,103 @@ +{ + "mockBidRequest": { + "id": "test-req", + "user": { + "ext": { + "consent" : "dummy" + } + }, + "imp": [ + { + "id": "test-req", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "account": "demo", + "location": "_adhese_prebid_demo_", + "format": "leaderboard", + "targets": + { + "ci": ["gent", "brussels"], + "ag": ["55"], + "tl": ["all"] + } + } + } + } + ], + "site": { + "id": "test", + "publisher": { + "id": "123" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy" + }, + "mockResponse": { + "status": 200, + "body": [{ + "origin": "JERLICIA", + "originInstance": "", + "ext": "js", + "slotName": "_main_page_-leaderboard", + "adType": "leaderboard", + "orderId": "888", + "id": "60613369", + "width": "728", + "height": "90", + "body": "
", + "tracker": "https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a", + "impressionCounter": "", + "extension": { + "prebid": { + "cpm": { + "amount": "1", + "currency": "USD" + } + } + } + }] + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "adm": "
", + "w": 728, + "h": 90, + "id": "", + "impid": "", + "price": 1.000000, + "dealid": "888", + "crid": "60613369", + "ext": { + "adFormat": "", + "adType": "leaderboard", + "adspaceId": "", + "libId": "", + "orderProperty": "", + "priority": "", + "viewableImpressionCounter": "" + } + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/adhese/params_test.go b/adapters/adhese/params_test.go new file mode 100644 index 00000000000..45024749b2d --- /dev/null +++ b/adapters/adhese/params_test.go @@ -0,0 +1,58 @@ +package adhese + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/prebid/prebid-server/openrtb_ext" +) + +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.BidderAdhese, json.RawMessage(validParam)); err != nil { + fmt.Println(err) + t.Errorf("Schema rejected Adhese params: %s", validParam) + } + } +} + +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.BidderAdhese, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"account": "demo", "location": "loc1", "format": "for1"}`, + `{"account": "demo", "location": "loc1", "format": "for1", "targets": { "ab": ["test", "test2"]}}`, +} + +var invalidParams = []string{ + `null`, + `nil`, + ``, + `[]`, + `true`, + `{"location": "loc1", "format": "for1"}`, + `{"account": "demo", "format": "for1"}`, + `{"account": "demo", "location": "loc1"}`, + `{"account": "demo", "location": "loc1", "format": "for1", "targets": null`, + `{"account": 5, "location": "loc1", "format": "for1"}`, + `{"account": "demo", "location": 5, "format": "for1"}`, + `{"account": "demo", "location": "loc1", "format": 5}`, + `{"account": "demo", "location": "loc1", "format": "for1", "targets": "test"}`, + `{"account": "demo", "location": "loc1", "format": "for1", "targets": 5}`, +} diff --git a/adapters/adhese/utils.go b/adapters/adhese/utils.go new file mode 100644 index 00000000000..9983be96d38 --- /dev/null +++ b/adapters/adhese/utils.go @@ -0,0 +1,45 @@ +package adhese + +import "github.com/mxmCherry/openrtb" + +type AdheseOriginData struct { + Priority string `json:"priority"` + OrderProperty string `json:"orderProperty"` + AdFormat string `json:"adFormat"` + AdType string `json:"adType"` + AdspaceId string `json:"adspaceId"` + LibId string `json:"libId"` + SlotID string `json:"slotID,omitempty"` + ViewableImpressionCounter string `json:"viewableImpressionCounter"` +} + +type AdheseExt struct { + Id string `json:"id"` + OrderId string `json:"orderId"` + ImpressionCounter string `json:"impressionCounter"` + Tag string `json:"tag,omitempty"` + Ext string `json:"ext"` +} + +type AdheseBid struct { + Origin string `json:"origin"` + OriginData openrtb.BidResponse `json:"originData"` + OriginInstance string `json:"originInstance,omitempty"` + Body string `json:"body,omitempty"` + Height string `json:"height"` + Width string `json:"width"` + Extension Prebid `json:"extension"` +} + +type Prebid struct { + Prebid CPM `json:"prebid"` +} + +type CPM struct { + Cpm CPMValues `json:"cpm"` +} + +type CPMValues struct { + Amount string `json:"amount"` + Currency string `json:"currency"` +} diff --git a/config/config.go b/config/config.go index 703606b2824..5c66f4cdf02 100755 --- a/config/config.go +++ b/config/config.go @@ -214,6 +214,7 @@ func (cfg *HostCookie) TTLDuration() time.Duration { const ( dummyHost string = "dummyhost.com" dummyPublisherID string = "12" + dummyAccountID string = "some_account" dummyGDPR string = "0" dummyGDPRConsent string = "someGDPRConsentString" dummyCCPA string = "1NYN" @@ -264,7 +265,7 @@ func validateAdapterEndpoint(endpoint string, adapterName string, errs configErr return append(errs, fmt.Errorf("Invalid endpoint template: %s for adapter: %s. %v", endpoint, adapterName, err)) } // Resolve macros (if any) in the endpoint URL - resolvedEndpoint, err := macros.ResolveMacros(*endpointTemplate, macros.EndpointTemplateParams{Host: dummyHost, PublisherID: dummyPublisherID}) + resolvedEndpoint, err := macros.ResolveMacros(*endpointTemplate, macros.EndpointTemplateParams{Host: dummyHost, PublisherID: dummyPublisherID, AccountID: dummyAccountID}) if err != nil { return append(errs, fmt.Errorf("Unable to resolve endpoint: %s for adapter: %s. %v", endpoint, adapterName, err)) } @@ -693,6 +694,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("adapters.33across.partner_id", "") v.SetDefault("adapters.adform.endpoint", "http://adx.adform.net/adx") v.SetDefault("adapters.adgeneration.endpoint", "https://d.socdm.com/adsv/v1") + v.SetDefault("adapters.adhese.endpoint", "https://ads-{{.AccountID}}.adhese.com/json") v.SetDefault("adapters.adkernel.endpoint", "http://{{.Host}}/hb?zone={{.ZoneID}}") v.SetDefault("adapters.adkerneladn.endpoint", "http://{{.Host}}/rtbpub?account={{.PublisherID}}") v.SetDefault("adapters.admixer.endpoint", "http://inv-nets.admixer.net/pbs.aspx") diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go index 15e57f55105..b91f01a7e9a 100755 --- a/exchange/adapter_map.go +++ b/exchange/adapter_map.go @@ -9,6 +9,7 @@ import ( ttx "github.com/prebid/prebid-server/adapters/33across" "github.com/prebid/prebid-server/adapters/adform" "github.com/prebid/prebid-server/adapters/adgeneration" + "github.com/prebid/prebid-server/adapters/adhese" "github.com/prebid/prebid-server/adapters/adkernel" "github.com/prebid/prebid-server/adapters/adkernelAdn" "github.com/prebid/prebid-server/adapters/admixer" @@ -87,6 +88,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter openrtb_ext.Bidder33Across: ttx.New33AcrossBidder(cfg.Adapters[string(openrtb_ext.Bidder33Across)].Endpoint), openrtb_ext.BidderAdform: adform.NewAdformBidder(client, cfg.Adapters[string(openrtb_ext.BidderAdform)].Endpoint), openrtb_ext.BidderAdgeneration: adgeneration.NewAdgenerationAdapter(cfg.Adapters[string(openrtb_ext.BidderAdgeneration)].Endpoint), + openrtb_ext.BidderAdhese: adhese.NewAdheseBidder(cfg.Adapters[string(openrtb_ext.BidderAdhese)].Endpoint), openrtb_ext.BidderAdkernel: adkernel.NewAdkernelAdapter(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdkernel))].Endpoint), openrtb_ext.BidderAdkernelAdn: adkernelAdn.NewAdkernelAdnAdapter(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdkernelAdn))].Endpoint), openrtb_ext.BidderAdmixer: admixer.NewAdmixerBidder(cfg.Adapters[strings.ToLower(string(openrtb_ext.BidderAdmixer))].Endpoint), diff --git a/macros/macros.go b/macros/macros.go index 9f9cfad2dcd..a9f77ea95fa 100644 --- a/macros/macros.go +++ b/macros/macros.go @@ -11,6 +11,7 @@ type EndpointTemplateParams struct { PublisherID string ZoneID string SourceId string + AccountID string } // UserSyncTemplateParams specifies params for an user sync URL template diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 7db59e69a4f..f2f8e7c67ab 100755 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -27,6 +27,7 @@ const ( Bidder33Across BidderName = "33across" BidderAdform BidderName = "adform" BidderAdgeneration BidderName = "adgeneration" + BidderAdhese BidderName = "adhese" BidderAdkernel BidderName = "adkernel" BidderAdkernelAdn BidderName = "adkernelAdn" BidderAdpone BidderName = "adpone" @@ -101,6 +102,7 @@ var BidderMap = map[string]BidderName{ "33across": Bidder33Across, "adform": BidderAdform, "adgeneration": BidderAdgeneration, + "adhese": BidderAdhese, "adkernel": BidderAdkernel, "adkernelAdn": BidderAdkernelAdn, "admixer": BidderAdmixer, diff --git a/openrtb_ext/imp_adhese.go b/openrtb_ext/imp_adhese.go new file mode 100644 index 00000000000..1c822018b24 --- /dev/null +++ b/openrtb_ext/imp_adhese.go @@ -0,0 +1,12 @@ +package openrtb_ext + +import ( + "encoding/json" +) + +type ExtImpAdhese struct { + Account string `json:"account"` + Location string `json:"location"` + Format string `json:"format"` + Keywords json.RawMessage `json:"targets,omitempty"` +} diff --git a/static/bidder-info/adhese.yaml b/static/bidder-info/adhese.yaml new file mode 100644 index 00000000000..742d78344ce --- /dev/null +++ b/static/bidder-info/adhese.yaml @@ -0,0 +1,11 @@ +maintainer: + email: info@adhese.com +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video \ No newline at end of file diff --git a/static/bidder-params/adhese.json b/static/bidder-params/adhese.json new file mode 100644 index 00000000000..a1bd608b7a8 --- /dev/null +++ b/static/bidder-params/adhese.json @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Adhese Adapter Parameters", + "description": "Validation for parameters handled by the Adhese adapter", + "type": "object", + "properties": { + "account": { + "type": "string", + "description": "Your Adhese account name. If unknown, please contact your sales rep" + }, + "location": { + "type": "string", + "description": "The location you want to refer to for a specific section or page, as defined in your Adhese inventory" + }, + "format": { + "type": "string", + "description": "The format you accept for this unit, as defined in your Adhese inventory" + }, + "targets": { + "type": "object", + "description": "Target params, as defined in your Adhese setup." + } + }, + "required": ["account", "location", "format"] +} diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go index f448da50005..20fce80c83a 100755 --- a/usersync/usersyncers/syncer_test.go +++ b/usersync/usersyncers/syncer_test.go @@ -78,6 +78,7 @@ func TestNewSyncerMap(t *testing.T) { adaptersWithoutSyncers := map[openrtb_ext.BidderName]bool{ openrtb_ext.BidderAdgeneration: true, + openrtb_ext.BidderAdhese: true, openrtb_ext.BidderAdoppler: true, openrtb_ext.BidderApplogy: true, openrtb_ext.BidderKidoz: true,