Skip to content

Conversation

@cto-clydo
Copy link
Contributor

@cto-clydo cto-clydo commented Sep 16, 2025

if err != nil {
return nil, fmt.Errorf("Failed to parse endpoint url: %v", err)
}
bidder := &ClydoAdapter{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can call this simply "adapter", the ClydoAdapter identification is already supplied by the package name. As you have it, referencing your adapter from outside the package would be ClydoAdapter.ClydoAdapter which looks a little redundant. See example below:

  package foo

  type adapter struct {
    endpoint string
  }
  
  func  Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
    return &adapter{endpoint: "https://www.foo.com"}, nil
  }

@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 23c9c07

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:48:	MakeBids		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:78:	prepareRequest		87.5%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:110:	prepareExtParams	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:126:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:138:	prepareBody		80.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:157:	prepareExt		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:166:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:190:	collectDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:210:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:218:	checkResponseStatus	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:235:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:243:	prepareSeatBids		84.6%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:269:	buildBidTypeMap		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:288:	getMediaTypeForBid	100.0%
total:								(statements)		92.1%

@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 653b568

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:48:	MakeBids		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:78:	prepareRequest		87.5%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:110:	prepareExtParams	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:126:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:138:	prepareBody		80.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:157:	prepareExt		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:166:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:190:	collectDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:210:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:218:	checkResponseStatus	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:235:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:243:	prepareSeatBids		84.6%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:269:	buildBidTypeMap		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:288:	getMediaTypeForBid	100.0%
total:								(statements)		92.1%

# EU: eu
# APAC: apac
# Please deploy this config in each of your datacenters with the appropriate regional subdomain
endpoint: 'http://us.clydo.io/{{.PartnerId}}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the commented lines, I suppose the us subdomain changes depending the region. Should the us part be put into its own macro?

1   # We have the following regional endpoint domains:
2   # US East: us
3   # US West: usw
4   # EU: eu
5   # APAC: apac
6   # Please deploy this config in each of your datacenters with the appropriate regional subdomain
7 - endpoint: 'http://us.clydo.io/{{.PartnerId}}'
  + endpoint: 'http://{{.Host}}.clydo.io/{{.PartnerId}}'
8   endpointCompression: gzip
9   geoscope:

}
requests = append(requests, reqData)
}
// fmt.Println(errors)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: can we remove commented lines?

reqCopy := *request
reqCopy.Imp = []openrtb2.Imp{imp}

extJSON, err := prepareExt(params)
Copy link
Contributor

@guscarreon guscarreon Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your adapter reads Imp[i].Ext.PartnerId to append it to the endpoint but, doesn't modify PartnerId itself, nor any part of Imp[i].Ext. Therefore, the jsonutil.Marshal(impExt) call inside prepareExt(params) seems unnecessary. Removing it would optimize:

138   func prepareBody(request *openrtb2.BidRequest, imp openrtb2.Imp, params *openrtb_ext.ImpExtClydo) ([]byte, error) {
139       reqCopy := *request
140       reqCopy.Imp = []openrtb2.Imp{imp}
141  
142 -     extJSON, err := prepareExt(params)
143 -     if err != nil {
144 -         return nil, err
145 -     }
146 -
147 -     reqCopy.Imp[0].Ext = extJSON
148  
149       body, err := jsonutil.Marshal(&reqCopy)
150       if err != nil {
151           return nil, err
152       }
153  
154       return body, nil
155   }
156  
157 - func prepareExt(impExt *openrtb_ext.ImpExtClydo) ([]byte, error) {
158 -     extJSON, err := jsonutil.Marshal(impExt)
159 -     if err != nil {
160 -         return nil, err
161 -     }
162 -
163 -     return extJSON, nil
164 - }
165  
166   func prepareHeaders(request *openrtb2.BidRequest) (http.Header, error) {

Do you agree, or is it better to leave it? Do you plan to modify the Imp[i].Ext in a future version of your adapter? Let me know your thoughts.

func prepareHeaders(request *openrtb2.BidRequest) (http.Header, error) {
baseHeaders := []struct {
key, value string
}{
Copy link
Contributor

@guscarreon guscarreon Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: For an easier read, can we create a type for the anonymous struct that holds the key, value pairs? We seem to use this anonymous struct a lot both in here and in the collectDeviceHeaders(request) function. Maybe even use a map so we don't need to create extra types?

166   func prepareHeaders(request *openrtb2.BidRequest) (http.Header, error) {
167 -     baseHeaders := []struct {
168 -         key, value string
169 -     }{
170 -         {"X-OpenRTB-Version", "2.5"},
171 -         {"Accept", "application/json"},
172 -         {"Content-Type", "application/json; charset=utf-8"},
173 -     }
174 -
175 -     deviceHeaders, err := collectDeviceHeaders(request)
176 -     if err != nil {
177 -         return nil, err
178 -     }
179 -
180 -     allHeaders := append(baseHeaders, deviceHeaders...)
    +     allHeaders := map[string]string{
    +         "X-OpenRTB-Version": "2.5",
    +         "Accept":            "application/json",
    +         "Content-Type":      "application/json; charset=utf-8",
    +     }
    +     allHeaders := appendDeviceHeaders(allHeaders, request)
181  
182       headers := make(http.Header)
183 -     for _, kv := range allHeaders {
184 -         headers.Add(kv.key, kv.value)
    +     for k, v := range allHeaders {
    +         headers.Add(k, v)
185       }
186  
187       return headers, nil
188   }
adapters/clydo/clydo.go

Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guscarreon Thanks for your review, I agree with your comments and have updated the adapter code

if response.Cur != "" {
bidResponse.Currency = response.Cur
} else {
bidResponse.Currency = "USD"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Currency field is already set the default value of "USD" inside of NewBidderResponseWithBidsCapacity(). The else clause could be removed:

61     bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
62     if response.Cur != "" {
63         bidResponse.Currency = response.Cur
64 -   } else {
65 -       bidResponse.Currency = "USD"
66     }
adapters/clydo/clydo.go

func getMediaTypeForBid(bid *openrtb2.Bid, bidTypeMap map[string]openrtb_ext.BidType) openrtb_ext.BidType {
// if mediaType, ok := bidTypeMap[bid.ImpID]; ok {
// return mediaType, nil
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those commented lines seemed like a good idea in order to cover the edge case where bid.ImpID isn't found in bidTypeMap. Can they get uncommented? If not, can they get removed?

@bsardo bsardo added the adapter label Sep 23, 2025
@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 182ef99

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:47:	MakeBids		92.9%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:75:	prepareRequest		87.5%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:107:	prepareExtParams	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:123:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:143:	prepareBody		85.7%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:157:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:177:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:195:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:203:	checkResponseStatus	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:220:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:228:	prepareSeatBids		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:253:	buildBidTypeMap		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:272:	getMediaTypeForBid	66.7%
total:								(statements)		92.4%

@guscarreon
Copy link
Contributor

@cto-clydo, the most recent commit to your PR is failing one of our validation scripts. It has to do with the format of the adapters/clydo/clydo.go file. From your local folder, can you run gofmt on it and make another commit so it stops complaining? This is the complete failed validation message:

Run ./validate.sh --nofmt --cov --race 10
gofmt needs to be run, 1 files have issues.  Below is a list of files to review:
adapters/clydo/clydo.go

@github-actions
Copy link

github-actions bot commented Oct 2, 2025

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 3d16eee

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:47:	MakeBids		92.9%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:75:	prepareRequest		87.5%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:107:	prepareExtParams	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:123:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:143:	prepareBody		85.7%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:157:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:177:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:195:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:203:	checkResponseStatus	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:220:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:228:	prepareSeatBids		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:253:	buildBidTypeMap		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:272:	getMediaTypeForBid	66.7%
total:								(statements)		92.4%

reqCopy := *request
reqCopy.Imp = []openrtb2.Imp{imp}

reqCopy.Imp[0].Ext = imp.Ext
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this assignment because all of the imp fields are already in reqCopy.Imp[0]

return nil, err
}

impIds, err := prepareImpIds(request)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is prepareImpIds() supposed to be called with a request that only has one imp in its Imp[] array as opposed to the original request? If not, if it's meant to be called as is in the current commit, with the original request as parameter, including all its original Imp[] elements: should the prepareImpIds() call get moved ouside the for loop in line 36?

Function openrtb_ext.GetImpIDs(request.Imp), called from prepareImpIds(request), traverses the n number of elements of request.Imp[] to build the impIds list and, given that prepareRequest(request, imp) gets called per every element of request.Imp[] in line 37 inside the for loop, impIds gets built multiple times. It gets built n times to be exact. Therefore, if prepareImpIds() is supposed to be passed the original request, and not a single imp request, we can optimize calling prepareImpIds(request) gets just once, outside the for loop.

 32   func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 33       var requests []*adapters.RequestData
 34       var errors []error
 35  
    +     impIds, err := prepareImpIds(request)
    +     if err != nil {
    +         return nil, append(errors, err)
    +     }
    +
 36       for _, imp := range request.Imp {
 37 -         reqData, err := a.prepareRequest(request, imp)
    +         reqData, err := a.prepareRequest(request, imp, impIds)
 38           if err != nil {
 39               errors = append(errors, err)
 40               continue
 41           }
 42           requests = append(requests, reqData)
 43       }
 44       return requests, errors
 45   }
 46  
 47 *-- 27 lines: func (a *adapter) MakeBids(--------------------------------------------------------------------------------
 74  
 75 - func (a *adapter) prepareRequest(request *openrtb2.BidRequest, imp openrtb2.Imp) (*adapters.RequestData, error) {
    + func (a *adapter) prepareRequest(request *openrtb2.BidRequest, imp openrtb2.Imp, impIds []string) (*adapters.RequestData, error) {
 76       params, err := prepareExtParams(imp)
 77 *-- 15 lines: if err != nil {--------------------------------------------------------------------------------------------
 92  
 93 -     impIds, err := prepareImpIds(request)
 94 -     if err != nil {
 95 -         return nil, err
 96 -     }
 97  
 98       return &adapters.RequestData{
 99           Method:  "POST",
100           Uri:     endpoint,
101           Body:    body,
102           Headers: headers,
103           ImpIDs:  impIds,
104       }, nil
105   }
adapters/clydo/clydo.go

Thoughts?

if err != nil {
return nil, err
}
headers, err := prepareHeaders(request)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside prepareRequest(request, imp), the outcome of prepareHeaders(request) doesn't seem to depend on the particular imp.Ext in question. Does prepareHeaders(request) need to be called more than once? If not, can it, similarly to prepareImpIds(request), get moved outside the for loop in line 36?

 32   func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 33       var requests []*adapters.RequestData
 34       var errors []error
 35  
    +     headers, err := prepareHeaders(request)
    +     if err != nil {
    +         return nil, append(errors, err)
    +     }
    +     
 36       for _, imp := range request.Imp {
 37 -         reqData, err := a.prepareRequest(request, imp)
    +         reqData, err := a.prepareRequest(request, imp, headers)
 38           if err != nil {
 39               errors = append(errors, err)
 40               continue
 41           }
 42           requests = append(requests, reqData)
 43       }
 44       return requests, errors
 45   }
 46  
 47 *-- 27 lines: func (a *adapter) MakeBids(-------------------------------------------------------------------------------------------------
 74  
 75 - func (a *adapter) prepareRequest(request *openrtb2.BidRequest, imp openrtb2.Imp) (*adapters.RequestData, error) {
    + func (a *adapter) prepareRequest(request *openrtb2.BidRequest, imp openrtb2.Imp, headers http.Header) (*adapters.RequestData, error) {
 76       params, err := prepareExtParams(imp)
 77       if err != nil {
 78           return nil, err
 79       }
 80 *--  7 lines: endpoint, err := a.prepareEndpoint(params)----------------------------------------------------------------------------------
 87       }
 88 -     headers, err := prepareHeaders(request)
 89 -     if err != nil {
 90 -         return nil, err
 91 -     }
 92  
 93       impIds, err := prepareImpIds(request)
 94       if err != nil {
 95           return nil, err
 96       }
 97  
 98       return &adapters.RequestData{
 99           Method:  "POST",
100           Uri:     endpoint,
101           Body:    body,
102           Headers: headers,
103           ImpIDs:  impIds,
104       }, nil
105   }

@github-actions
Copy link

github-actions bot commented Oct 9, 2025

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 45715b3

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:57:	MakeBids		92.9%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:85:	prepareRequest		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:108:	prepareExtParams	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:124:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:144:	prepareBody		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:156:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:176:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:194:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:202:	checkResponseStatus	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:219:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:227:	prepareSeatBids		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:252:	buildBidTypeMap		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:271:	getMediaTypeForBid	66.7%
total:								(statements)		92.4%

@cto-clydo cto-clydo requested a review from guscarreon October 9, 2025 15:46
}

func getMediaTypeForBid(bid *openrtb2.Bid, bidTypeMap map[string]openrtb_ext.BidType) openrtb_ext.BidType {
if mediaType, ok := bidTypeMap[bid.ImpID]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are imp.ID collisions likely? In other words, is an edge case like the one shown below, where two imp.IDs are the same for two imp elements with different formats, feasible?

req.Imp = []openrtb2.Imp{
    {ID: "sameID", Video: &openrtb2.Video{ /* not-nil */ },
    {ID: "sameID", Banner: &openrtb2.Banner{ /* not-nil */ },
    {ID: "anotherID", Native: &openrtb2.Native{ /* not-nil */ },
}

If this edge case ever presents itself, it seems that the the current logic would overwrite the "sameID" entry in bidTypeMap. bidTypeMap would look like:

bidTypeMap := map[string]openrtb_ext.BidType{
    "sameID":    openrtb_ext.BidTypeBanner,
    "anotherID": openrtb_ext.BidTypeNative,
}

Which would mislabel one bid as a banner, when in reality it is a video. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it's better to validate duplicates

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scenario can occur in the case of a multi-format request. Does Clydo support multi-format requests? If so, would it be better to determine the media type from the bid instead of relying on the impression?

responseData *adapters.ResponseData,
) (*adapters.BidderResponse, []error) {
if errResp := checkResponseStatus(responseData); errResp != nil {
return nil, errResp
Copy link
Contributor

@guscarreon guscarreon Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with the checkResponseStatus(responseData) function as it's not too big nor hard to maintain. However, most of the logic in checkResponseStatus(responseData) is already in the adapter framework-wide functions adapters.CheckResponseStatusCodeForErrors(responseData) and adapters.IsResponseStatusCodeNoContent(responseData) found in adapters/response.go. I think it'd be better to use those functions in order to not maintain more lines of code than we need to, but I leave it up to you.

Let me know your thoughts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense

@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, ef565a5

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:57:	MakeBids		93.8%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:89:	prepareRequest		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:112:	prepareExtParams	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:128:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:148:	prepareBody		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:160:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:180:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:198:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:206:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:214:	prepareSeatBids		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:239:	buildBidTypeMap		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:264:	getMediaTypeForBid	66.7%
total:								(statements)		91.5%

@cto-clydo cto-clydo requested a review from guscarreon October 27, 2025 10:44
var bidderExt adapters.ExtImpBidder
if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil {
return nil, &errortypes.BadInput{
Message: "missing ext.bidder",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An unmarshalling error doesn’t always indicate a missing field — it could also result from formatting issues or incorrect data types. We should check for an empty imp.ext and handle such errors gracefully.

responseData *adapters.ResponseData,
) (*adapters.BidderResponse, []error) {
if adapters.IsResponseStatusCodeNoContent(responseData) {
return nil, []error{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Can we return nil instead of empty error object?

}

func getMediaTypeForBid(bid *openrtb2.Bid, bidTypeMap map[string]openrtb_ext.BidType) openrtb_ext.BidType {
if mediaType, ok := bidTypeMap[bid.ImpID]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scenario can occur in the case of a multi-format request. Does Clydo support multi-format requests? If so, would it be better to determine the media type from the bid instead of relying on the impression?

}

switch {
case imp.Video != nil:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use metadata from the bid to determine the media type instead of relying on the impression? Relying solely on the impression could cause issues in multi-format requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clydo does not support multi-format requests, so let's stick with impression-based mapping

@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 499ee6f

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:57:	MakeBids		93.8%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:89:	prepareRequest		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:112:	prepareExtParams	90.9%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:138:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:158:	prepareBody		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:170:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:190:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:208:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:216:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:224:	prepareSeatBids		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:249:	buildBidTypeMap		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:274:	getMediaTypeForBid	66.7%
total:								(statements)		90.9%

@bsardo bsardo assigned guscarreon and unassigned przemkaczmarek Oct 28, 2025
geoscope:
- global
maintainer:
email: cto@clydo.io
Copy link
Collaborator

@przemkaczmarek przemkaczmarek Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waiting for response

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verified:
image

Copy link
Contributor

@guscarreon guscarreon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your adapter looks good to me. LEft a couple of nitpicks and a question

return response, nil
}

func prepareSeatBids(seatBids []openrtb2.SeatBid, bidTypeMap map[string]openrtb_ext.BidType) ([]*adapters.TypedBid, []error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: In its current form, under no scenario prepareSeatBids() returns an error nor an array or errors. Should we remove and simplify the function signature?

223
224 - func prepareSeatBids(seatBids []openrtb2.SeatBid, bidTypeMap map[string]openrtb_ext.BidType) ([]*adapters.TypedBid, []error) {
    + func prepareSeatBids(seatBids []openrtb2.SeatBid, bidTypeMap map[string]openrtb_ext.BidType) []*adapters.TypedBid {
225       var typedBids []*adapters.TypedBid
226 -     var errors []error
227  
228       if seatBids == nil {
adapters/clydo/clydo.go

for _, seatBid := range seatBids {
if seatBid.Bid == nil {
continue
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: no need for the checks as the range keyword takes care of the nil value scenario

224   func prepareSeatBids(seatBids []openrtb2.SeatBid, bidTypeMap map[string]openrtb_ext.BidType) ([]*adapters.TypedBid, []error) {
225       var typedBids []*adapters.TypedBid
226       var errors []error
227  
228 -     if seatBids == nil {
229 -         return typedBids, nil
230 -     }
231  
232       for _, seatBid := range seatBids {
233 -         if seatBid.Bid == nil {
234 -             continue
235 -         }
236           for i := range seatBid.Bid {
237               bid := &seatBid.Bid[i]
238               bidType := getMediaTypeForBid(bid, bidTypeMap)
adapters/clydo/clydo.go

case imp.Banner != nil:
bidTypeMap[imp.ID] = openrtb_ext.BidTypeBanner
default:
return nil, &errortypes.BadInput{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your static/bidder-info/clydo.yaml file lists audio as supported media type but, if a request with an imp.Audio was to come, your buildBidTypeMap(imps []openrtb2.Imp) function would throw an errortypes.BadInput error in line 266. Should audio be removed from the list? OR should it be allowed in buildBidTypeMap(imps []openrtb2.Imp)?

14 capabilities:
15   app:
16     mediaTypes:
17       - banner
18       - video
19       - audio
20       - native
21   site:
22     mediaTypes:
23       - banner
24       - video
25       - audio
26       - native
static/bidder-info/clydo.yaml

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added audio to buildBidTypeMap, clydo can support it

@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, cd875f1

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:57:	MakeBids		87.5%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:89:	prepareRequest		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:112:	prepareExtParams	90.9%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:138:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:158:	prepareBody		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:170:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:190:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:208:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:216:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:224:	prepareSeatBids		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:241:	buildBidTypeMap		72.7%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:268:	getMediaTypeForBid	66.7%
total:								(statements)		89.7%

guscarreon
guscarreon previously approved these changes Oct 29, 2025
Copy link
Contributor

@guscarreon guscarreon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Thank you @cto-clydo for addressing my feedback. I bnelieve @przemkaczmarek sent a test email to cto@clydo.io to verify if it's active.

# EU: eu
# APAC: apac
# Please deploy this config in each of your datacenters with the appropriate regional subdomain
endpoint: 'http://{{.Region}}.clydo.io/{{.PartnerId}}'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only us is reachable. why the rest is not reachable?
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, it's okay for now, we want to have adapter prepared for other regions before setting up all the rest infrastructure

@github-actions
Copy link

Code coverage summary

Note:

  • Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors
  • Coverage summary encompasses all commits leading up to the latest one, 2a05eca

clydo

Refer here for heat map coverage report

github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:21:	Builder			100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:32:	MakeRequests		93.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:57:	MakeBids		87.5%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:89:	prepareRequest		90.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:112:	prepareExtParams	90.9%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:138:	prepareEndpoint		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:158:	prepareBody		83.3%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:170:	prepareHeaders		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:190:	appendDeviceHeaders	100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:208:	prepareImpIds		75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:216:	prepareBidResponse	75.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:224:	prepareSeatBids		100.0%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:241:	buildBidTypeMap		72.7%
github.com/prebid/prebid-server/v3/adapters/clydo/clydo.go:268:	getMediaTypeForBid	66.7%
total:								(statements)		89.7%

@bsardo bsardo merged commit c9b63e1 into prebid:master Nov 19, 2025
6 checks passed
danielbaud pushed a commit to alliance-gravity/prebid-server-go that referenced this pull request Nov 25, 2025
shunj-nb pushed a commit to ParticleMedia/prebid-server that referenced this pull request Dec 15, 2025
shunj-nb added a commit to ParticleMedia/prebid-server that referenced this pull request Dec 15, 2025
* Dianomi: Update user syncs to send gdpr_consent (prebid#4345)

* MobileFuse: Remove tagid_src and pub_id params (prebid#4303)

* Remove tagid_src ext from MobileFuse Adapter

* remove pub_id query param

* removed comment

* Simplify Endpoint assignment in MobileFuseAdapter

* New Adapter: Flatads (prebid#4243)

Co-authored-by: wuzhijian <wuch1k1n@qq.com>

* Rubicon: Add bid meta seat (prebid#4348)

* Gothamads: Add Intenze alias (prebid#4319)

* GumGum: Collect ad unit name for reporting (prebid#4302)

* Seedtag: Fix required content-type header on http calls (prebid#4299)

* Kobler: Remove sensitive device and user data (prebid#4295)

* New Adapter: Nexx360 (prebid#4286)

Co-authored-by: Gabriel Chicoye <gabriel@macbookrogab24g.lan>

* HTTP Fetcher: Implement RFC 3986 compatibility as optional (prebid#4272)

* Targeting: Add configurable targeting prefix (prebid#4355)

* Pubmatic: Set bid.meta.mediaType=video when bid.ext.ibv=true (prebid#4189)

* Rules Engine Module: Phase 1 (prebid#4407)

Co-authored-by: Veronika Solovei <kalypsonika@gmail.com>
Co-authored-by: guscarreon <guscarreon@gmail.com>

* New Adapter: Sparteo (prebid#4275)

* PubMatic: Fix missing bid type in bid response (prebid#4417)

* Fix: Remove module per request JSON marshal and add custom viper decoder (prebid#4422)

* RichAudience: change endpoint to https (prebid#4384)

Co-authored-by: IAN <ian.musachs@exte.com>

* Missena: Pass full openrtb request (prebid#4394)

* New Adapter: Rediads (prebid#4233)

* Zeta Global SSP: Declare OpenRTB 2.6 and GPP support (prebid#4389)

* Record metric unsuccessful for PBC non-200 response status code or error (prebid#4341)

Co-authored-by: oleksandr <oleksandr@assertive.ai>

* New Adapter: Akcelo (prebid#4237)

* New Adapter: Zentotem (prebid#4053)

* New Adapter: Exco (prebid#4250)

* Floors: Fix panic while getting adunit code for signaling (prebid#4424)

* Stroeercore: Add adomain to bids (prebid#4392)

* VIS.X: Relay bid currency from bid response (prebid#4381)

* TMax: Add default host config (prebid#4430)

* Fix the package (iterators) to agree with the dir (iterutil). (prebid#4447)

* TheTradeDesk: Throw error for malformed endpoint url (prebid#4419)

* Smartadserver : Send multi-impression requests without flattening (prebid#4402)

Co-authored-by: nlesommer <nlesommer@equativ.com>
Co-authored-by: gtodeschi <gregoire.todeschi@gmail.com>

* RTB House: Remove PAAPI signals from imp[].ext (prebid#4399)

* GumGum: Enable Opt-In change notification (prebid#4390)

* Tappx: Add GPID support (prebid#4438)

Co-authored-by: Jordi Arnau <jarnau@tappx.com>

* New Adapter: progx - Vidazoo alias (prebid#4428)

* New Adapter: Kuantyx - Aso alias (prebid#4420)

* MinuteMedia: Add test endpoint (prebid#4425)

* Adagio: Add site bidder param and web inventory tests (prebid#4403)

Co-authored-by: Godefroi Roussel <groussel@adagio.io>

* Modularity: Add hook code to module invocation context (prebid#4036)

* Rubicon: Pass ext.prebid.multibid[].maxbids to XAPI (prebid#4412)

* OpenX: Add gpp params to user sync (prebid#4445)

Co-authored-by: gmiedlar-ox <gabriela.miedlar@openx.com>

* New Adapter: Blis (prebid#4304)

Co-authored-by: Tomas Koutny <tomas@blis.com>

* Ogury: Support gpp for cookie sync (prebid#4406)

* TheTradeDesk: Resolve AUCTION_PRICE macro (prebid#4448)

* Fix: Set account http fetcher defaults enabling env vars (prebid#4460)

* Bidder throttling code to increase network stability. (prebid#4415)

* Adding request throttling to bidder requests

* Add latency health

* Adds new config options, metrics, and fixes

* Set default window to 1000 and fix error type typo

* Addresses PR comments

* More PR feedback

* Proper handling of the atomic uint in tests

* Yieldlab: Forward ADomain to OpenRTB bid (prebid#4404)

* Yandex: Add video support (prebid#4344)

* Request: Add hb_env=amp targeting to AMP responses (prebid#4414)

* Pubmatic: Forward skadn object in bid request (prebid#4453)

* Adds missing defaults to network throttling code (prebid#4477)

* New Adapter: Tagoras - Vidazoo alias (prebid#4329)

Co-authored-by: anna-y-perion <annay@perion.com>

* New Adapter: Omnidex - Vidazoo alias (prebid#4441)

* Define An Adapter As White Label Only (prebid#4461)

* Rules Engine Module: Result functions fix (prebid#4451)

* Account: Support bid rounding options (prebid#4470)

* Sovrn: Fix passing through imp.ext.gpid (prebid#4413)

* Smartadserver: Add second endpoint for programmatic guaranteed (prebid#4467)

Co-authored-by: Guillaume Laubier <glaubier@equativ.com>

* sspBC: Updates moving operations to backend service (prebid#4351)

* New Adapter: Adipolo - Xeworks alias (prebid#4350)

Co-authored-by: And-Rud <andrii@xe.works>
Co-authored-by: rbstdev <devgit204@xe.works>

* Modules: Exitpoint Stage (prebid#4435)

* New Adapter: Afront (prebid#4380)

* Harden HTTP Response Body Handling (prebid#4489)

* New Adapter: TeqBlaze (prebid#4480)

* Onetag: imp.ext read generalization (prebid#4446)

Co-authored-by: lorenzob <l.baglini@onetag.com>

* Rules Engine Module: Configurable cache update frequency (prebid#4423)

Co-authored-by: VeronikaSolovei9 <vsolovei@microsoft.com>

* New Adapter: RocketLab (prebid#4383)

* change zmaticoo.yaml endpoint (prebid#4471)

Co-authored-by: Quentin.zuo <quentin.zuo@eclicktech.com.cn>

* Metrics: Record GVL fetch count (prebid#4500)

* TheTradeDesk: Resolve burl if not resolved (prebid#4481)

* New Adapter: pinkLion (prebid#4376)

* Metrics: Record HTTP connections wanted and obtained (prebid#4518)

* Metrics: Record incoming request sizes (prebid#4495)

* Modules: Execute mutations in the order they are listed (prebid#4279)

* 4278 Execute mutations in the sequence they are listed.

* Ensure that the rejected channel is closed (once) on reject

* Use stack var.

* Add comments.

* Ensure rejected is closed.

* Just return explicitly in all 3 cases.

* Keep the same style - of passing the params to the go routine.

* Revert "Modules: Execute mutations in the order they are listed (prebid#4279)" (prebid#4529)

This reverts commit 93c17c2.

* Revert "Metrics: Record HTTP connections wanted and obtained (prebid#4518)" (prebid#4538)

* New Adapter: Nativery (prebid#4321)

Co-authored-by: Andrea Fassina <fasenderos@gmail.com>
Co-authored-by: nicoladellamorte <nicola.dellamorte@nativery.com>

* E-Planning: Add support for adomain (prebid#4472)

* SmileWanted: Append zoneId to endpoint path (prebid#4468)

Co-authored-by: QuentinGallard <quentin.gallard@digitalnolimit.com>

* Add configurable dialer timeouts to HTTP clients (prebid#4511)

* New Adapter: 360playvid (prebid#4395)

* New Adapter: MediaYo (prebid#4391)

* 33across: Make zoneId the preferred option (prebid#4531)

* 33across: Remove deprecated video.placement (prebid#4530)

* New Adapter: RobustApps - Xeworks alias (prebid#4434)

Co-authored-by: And-Rud <andrii@xe.works>
Co-authored-by: rbstdev <devgit204@xe.works>

* Adagio: Remove max length on params (prebid#4524)

Co-authored-by: Godefroi Roussel <groussel@adagio.io>

* fwssp: Add iframe usersync (prebid#4487)

Co-authored-by: wenyuanzhang <wenyuanzhang@freewheel.tv>

* Module: Scope3 Real-Time Data (prebid#4397)

* Add Scope3 Real-Time Data (RTD) module

This module integrates Scope3's Real-Time Data API to provide audience
segments for targeting in Prebid Server auctions.

Features:
- Fetches real-time audience segments from Scope3 API
- Adds targeting data to bid requests via hooks system
- Thread-safe segment storage during auction lifecycle
- Configurable timeout and endpoint settings
- Graceful error handling that doesn't fail auctions

The module implements three hook stages:
- Entrypoint: Initialize module context
- Raw Auction Request: Fetch segments from Scope3 API
- Processed Auction Request: Add segments to targeting data

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add LiveRamp ATS integration and execution order documentation

- Document proper execution order when using with LiveRamp ATS
- Add user identifier detection for RampID integration
- Include configuration examples for sequential module execution
- Enhance API requests with available user identifiers
- Add comprehensive documentation for Yahoo deployment scenario

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add LiveRamp ATS envelope support for publishers without sidecar

- Support forwarding encrypted ATS envelopes directly to Scope3 API
- Check multiple envelope locations: user.ext.liveramp_idl, user.ext.ats_envelope, ext.liveramp_idl
- Prioritize sidecar RampID over envelope when both available
- Document both sidecar and envelope integration patterns
- Add note about Scope3 needing LiveRamp partner authorization

This enables publishers without LiveRamp sidecar to still benefit from
LiveRamp ATS user signals via encrypted envelope forwarding.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Clean up debug code and finalize production-ready Scope3 RTD module

- Remove all debug logging statements
- Streamline segment storage and retrieval between hooks
- Finalize request-level targeting for GAM integration
- Production-ready code with proper error handling
- Complete documentation with configuration examples

The module is now ready for production deployment with:
- Successful Scope3 API integration
- LiveRamp ATS compatibility (sidecar and envelope)
- GAM targeting data output
- Thread-safe segment management

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Simplify targeting output to single GAM-compatible format

- Remove duplicate data.scope3_segments array format
- Keep only targeting.hb_scope3_segments as comma-separated string
- Follows standard header bidding targeting key conventions
- Optimized for GAM key-value targeting integration

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add unit tests for Scope3 RTD module

- Add basic unit tests for module builder and hook functions
- Test invalid config handling and error cases
- Test entrypoint hook initialization
- Test processed auction hook with no segments
- Satisfy CI requirements for test coverage

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix Go formatting issues

- Remove trailing whitespace in module.go
- Add missing newline at end of module_test.go
- Satisfy gofmt validation requirements

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address PR feedback: Add caching, improve LiveRamp integration, enhance configurability

Key improvements based on reviewer feedback:
- Add intelligent caching with configurable TTL to handle repeated requests
- Set 60-second default cache TTL for frequency cap compatibility
- Improve LiveRamp identifier detection across multiple locations
- Remove unsubstantiated partnership claims and improve documentation
- Add cache_ttl_seconds and bid_meta_data configuration options
- Implement MD5-based cache keys from user IDs and site context
- Add comprehensive test coverage for new caching functionality
- Update documentation to explain targeting vs bid.meta approach
- Change default timeout to 1000ms for better API compatibility

Addresses concerns about:
- Performance with hundreds of identical requests per user session
- Flexibility in targeting data output (bid.meta future enhancement noted)
- Accurate LiveRamp integration documentation
- Proper hook implementation code naming

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Complete PR feedback implementation: Response-level segments with GAM targeting

Major changes to address all PR reviewer feedback:

**Response Format Changes:**
- Move from request targeting to auction response data per reviewer feedback
- Change hook stage from processed_auction_request to auction_response
- Add segments to response.ext.scope3.segments for publisher control
- Add individual GAM targeting keys when add_to_targeting=true (e.g., gmp_eligible=true)

**Configuration Updates:**
- Rename bid_meta_data to add_to_targeting for clarity
- Add comprehensive GAM integration with individual segment keys
- Remove incorrect LiveRamp RTD adapter references from README
- Update hook configuration examples to use auction_response stage

**API Integration Fixes:**
- Correct segment parsing to exclude destination field (triplelift.com)
- Extract only actual segments from imp[].ext.scope3.segments[]
- Maintain working authentication and caching functionality

**Enhanced Testing:**
- Add comprehensive mock API integration tests
- Test both response formats (scope3 + targeting sections)
- Test error handling with mock server responses
- Apply gofmt formatting to all code

**Publisher Benefits:**
- Full control over segment usage via response.ext.scope3.segments
- Optional automated GAM integration via individual targeting keys
- Flexible configuration for different use cases
- Maintains caching for high-frequency scenarios

Addresses all PR reviewer concerns while providing maximum publisher flexibility.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address PR feedback: Add optimized HTTP Transport for high-frequency API calls

  Per reviewer feedback (@gravelg): 'if we're going to be make a lot of calls,
  we should use a Transport with better defaults'

  - MaxIdleConns: 100 (increased connection pool)
  - MaxIdleConnsPerHost: 10 (multiple connections per host)
  - IdleConnTimeout: 90s (longer connection reuse)
  - ForceAttemptHTTP2: true (HTTP/2 for better performance)
  - DisableCompression: false (bandwidth optimization)

  🤖 Generated with [Claude Code](https://claude.ai/code)
  Co-Authored-By: Claude <noreply@anthropic.com>

* run gofmt

* update default endpoint

* fix test

* address comments

* more review comments

* address more comments

* remove unused enhanceRequestWithUserIDs method

* jsonutil, add more tests

* Add privacy field masking for Scope3 RTD module

Implement comprehensive privacy protection by masking sensitive user data
before sending bid requests to the Scope3 API while preserving essential
targeting capabilities.

Features:
- Configurable field masking with privacy-first defaults
- Geographic data truncation with configurable precision (default: 2 decimals ~1.1km)
- Identity provider filtering with allowlist for preserved EIDs
- Always removes: IP addresses, user IDs, demographics, first-party data
- Always preserves: device characteristics, country/region, site/app context
- Comprehensive test coverage (92.3%) with edge case handling
- All linting checks pass with zero issues

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix cache key generation for proper per-user caching

- Use SHA-256 hashed user.id as fallback when privacy-safe identifiers are unavailable
- Maintains per-user cache segmentation for performance while protecting privacy
- Privacy-safe identifiers (RampID, LiverampIDL) take priority over hashed user.id
- Prevents accidental data leakage by returning nil on masking failures
- Add configuration validation for geo precision (max 4 decimal places)
- Add comprehensive tests for cache key behavior and configuration validation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix gofmt formatting in module_test.go

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* review fixes

* more review comments

* make it async

* address more comments

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Gabriel Gravel <ggravel@scope3.com>

* Metrics: Add connection dial metrics by adapter (prebid#4528)

* KueezRTB: Remove additionalProperties from schema (prebid#4490)

* Kargo: Add email to codepath notification workflow (prebid#4484)

Co-authored-by: Nick Llerandi <nick.llerandi@kargo.com>

* New Adapter: Contxtful (prebid#4443)

Co-authored-by: rufiange <sebastien@rufiange.com>

* Modules: Exitpoint Hook typo fix (prebid#4542)

* Consumable: Declare geoscope (prebid#4496)

* Connatix: Copy entire imp[i].ext (prebid#4521)

* Fix: Preload Prometheus adapter connection dial metric labels when enabled (prebid#4543)

Co-authored-by: oleksandr <oleksandr@assertive.ai>

* Host Option To Use OS Certs (prebid#4536)

* CPMStar: imp.ext passthrough (prebid#4450)

* MetaX: Add redirect user sync (prebid#4550)

Signed-off-by: Kehan Pan <kehan.pan@metaxsoft.com>

* New Adapter: Xapads - AdKernel alias (prebid#4534)

* Connatix: Add GPP macros (prebid#4525)

* OpenX: Return buyer exts in response (prebid#4507)

Co-authored-by: Rafal Sieczka <rafal.sieczka@openx.com>

* Yandex: Set referer and target-ref to site.page (prebid#4488)

* Nextmillennium: New fields and adapter version update (prebid#4486)

* Accounts: Add coop cookiesync priority groups (prebid#4561)

* Mobkoi: Remove url endpoint override (prebid#4555)

* GDPR: Move enforcement processing upstream (prebid#4567)

* Actions: Add publish to docker hub workflow (prebid#4558)

* Omnidex: Add GVL ID (prebid#4568)

* Adagio: Fix typo (prebid#4570)

* Improve Digital: Switch to HTTPS (prebid#4559)

* Mobkoi: Update endpoint (prebid#4523)

* Remove flaky agma test (prebid#4578)

* New Adapter: appStockSSP (prebid#4502)

Co-authored-by: Kanceliarenko <kostiantyn.k@teqblaze.com>

* Rules Engine Module: Dynamic ruleset from YAML geoscopes (prebid#4509)

* In order to protect users of prebid-server that don't use CGO, add build flag (prebid#4058)

* In order to protect users of prebid-server that don't use CGO, add build flag.

* Conditionally configure fiftyonedegrees.

* Because the module file is auto-generated, let it include fiftyonedegrees but just explain that it can't be enabled.

* include used packages.

* fix builder.

* Remove unused file.

* Add a test for the Builder when CGO is not enabled.

* New Adapter: Gravite (prebid#4547)

* New Adapter: Goldbach (prebid#4476)

* New Adapter: Showheroes (prebid#4533)

* New Adapter: Performist - Limelight Alias (prebid#4283)

* Connatix: Support GZIP (prebid#4575)

* RTBHouse: PMP removal, publisherId parameter extraction (prebid#4564)

* Adnuntius: Pass targeting to ad server (prebid#4545)

* New Adapter: Boldwin Rapid (prebid#4478)

* Scope3: Various fixes to RTD module (prebid#4544)

* PubMatic: Pass alias bidder name through (prebid#4588)

* BidTheatre: Update endpoint and add redirect user sync (prebid#4562)

* CWire: Add userSync (prebid#4516)

* New Adapter: Clydo (prebid#4535)

* New Adapter: Microsoft (msft) (prebid#4592)

* Syncer: Allow Duplicate Syncer Key For Identical Config (prebid#4622)

* Adagio: Enable site capability (prebid#4590)

* Adagio: Remove hardcoded seat name (prebid#4596)

* Warn in auction response for bidders blocked by privacy settings (prebid#4537)

Co-authored-by: oleksandr <oleksandr@assertive.ai>

* Logging: Add interface with default glog implementation (prebid#4085)

Co-authored-by: postindustria-code <oss@postindustria.com>

* msp 25-12

---------

Signed-off-by: Kehan Pan <kehan.pan@metaxsoft.com>
Co-authored-by: Michael Stevens <michael.stevens@dianomi.com>
Co-authored-by: tomaszbmf <142428312+tomaszbmf@users.noreply.github.com>
Co-authored-by: FlatAds <83808812+flatads@users.noreply.github.com>
Co-authored-by: wuzhijian <wuch1k1n@qq.com>
Co-authored-by: Anton Babak <76536883+AntoxaAntoxic@users.noreply.github.com>
Co-authored-by: support-gotham-ads <support@gothamads.com>
Co-authored-by: ShayanK16GumGum <shayan.khan@ic.gumgum.com>
Co-authored-by: sangarbe <sangarbe@gmail.com>
Co-authored-by: Tommy Pettersen <42890605+TommyHPettersen@users.noreply.github.com>
Co-authored-by: Gabriel Chicoye <gabriel.chicoye@gmail.com>
Co-authored-by: Gabriel Chicoye <gabriel@macbookrogab24g.lan>
Co-authored-by: Sigma Software <prebid.opensource@sigma.software>
Co-authored-by: pm-priyanka-bagade <156899734+pm-priyanka-bagade@users.noreply.github.com>
Co-authored-by: Brian Sardo <1168933+bsardo@users.noreply.github.com>
Co-authored-by: Veronika Solovei <kalypsonika@gmail.com>
Co-authored-by: guscarreon <guscarreon@gmail.com>
Co-authored-by: t-sormonte <t.sormonte@sparteo.com>
Co-authored-by: Isha Bharti <isha.bharti@pubmatic.com>
Co-authored-by: Rich Audience <sergi.gimenez@richaudience.com>
Co-authored-by: IAN <ian.musachs@exte.com>
Co-authored-by: Jean-Sébastien Ney <jeansebastien.ney@gmail.com>
Co-authored-by: rediads <123890182+rediads@users.noreply.github.com>
Co-authored-by: abermanov-zeta <95416296+abermanov-zeta@users.noreply.github.com>
Co-authored-by: linux019 <anode.dev@gmail.com>
Co-authored-by: oleksandr <oleksandr@assertive.ai>
Co-authored-by: Roger <104763658+rogerDyl@users.noreply.github.com>
Co-authored-by: zentotem <programmatic@zentotem.net>
Co-authored-by: Pete <petropo@ex.co>
Co-authored-by: Nikhil Vaidya <102963966+pm-nikhil-vaidya@users.noreply.github.com>
Co-authored-by: Philip Watson <philip.watson@adscale.co.nz>
Co-authored-by: Vladimir Fedoseev <vl.fedoseev@gmail.com>
Co-authored-by: Sheridan C Rawlins <41922797+scr-oath@users.noreply.github.com>
Co-authored-by: andre-gielow-ttd <124626380+andre-gielow-ttd@users.noreply.github.com>
Co-authored-by: Nathan Le Sommer <lesommer.nathan@gmail.com>
Co-authored-by: nlesommer <nlesommer@equativ.com>
Co-authored-by: gtodeschi <gregoire.todeschi@gmail.com>
Co-authored-by: Piotr Jaworski <109736938+piotrj-rtbh@users.noreply.github.com>
Co-authored-by: sindhuja-sridharan <148382298+sindhuja-sridharan@users.noreply.github.com>
Co-authored-by: jordi-tappx <jarnau@techsoulogy.com>
Co-authored-by: Jordi Arnau <jarnau@tappx.com>
Co-authored-by: Anna Yablonsky <annay@perion.com>
Co-authored-by: Adserver.Online <61009237+adserver-online@users.noreply.github.com>
Co-authored-by: inna <innayare@gmail.com>
Co-authored-by: GodefroiRoussel <GodefroiRoussel@users.noreply.github.com>
Co-authored-by: Godefroi Roussel <groussel@adagio.io>
Co-authored-by: Kacper Fus <kacper.fus@openx.com>
Co-authored-by: gmiedlar-ox <gabriela.miedlar@openx.com>
Co-authored-by: tomaskoutny-blis <60094686+tomaskoutny-blis@users.noreply.github.com>
Co-authored-by: Tomas Koutny <tomas@blis.com>
Co-authored-by: Vincent Bachelier <vincent@ogury.co>
Co-authored-by: hhhjort <31041505+hhhjort@users.noreply.github.com>
Co-authored-by: yuu.t <tongyu24@hotmail.com>
Co-authored-by: Dmitry Ermakov <skfyann@gmail.com>
Co-authored-by: Saar Amrani <saar120@gmail.com>
Co-authored-by: Scott Kay <noreply@syntaxnode.com>
Co-authored-by: Sandy Janicki <sejanick@users.noreply.github.com>
Co-authored-by: Guillaume Laubier <guillaume.laubier@hotmail.fr>
Co-authored-by: Guillaume Laubier <glaubier@equativ.com>
Co-authored-by: mabielinski-wpm <155963187+mabielinski-wpm@users.noreply.github.com>
Co-authored-by: Andrii Rudyk <96918101+And-Rud@users.noreply.github.com>
Co-authored-by: And-Rud <andrii@xe.works>
Co-authored-by: rbstdev <devgit204@xe.works>
Co-authored-by: Afrontio <support@afront.io>
Co-authored-by: MaksymTeqBlaze <maksym.pavliv@teqblaze.com>
Co-authored-by: esimonelli@onetag <136568337+EmanueleSimonelli@users.noreply.github.com>
Co-authored-by: lorenzob <l.baglini@onetag.com>
Co-authored-by: VeronikaSolovei9 <vsolovei@microsoft.com>
Co-authored-by: Leandro Marty <leandro.marty@rocketlab.ai>
Co-authored-by: g-coder-baiai <77920802+g-coder-baiai@users.noreply.github.com>
Co-authored-by: Quentin.zuo <quentin.zuo@eclicktech.com.cn>
Co-authored-by: prebidPinkLion <prebid@pinklion.io>
Co-authored-by: andreafassina <127768714+andreafassina@users.noreply.github.com>
Co-authored-by: Andrea Fassina <fasenderos@gmail.com>
Co-authored-by: nicoladellamorte <nicola.dellamorte@nativery.com>
Co-authored-by: Agustin Insua <Nistenf@users.noreply.github.com>
Co-authored-by: Quentin Gallard <QuentinGallard@users.noreply.github.com>
Co-authored-by: QuentinGallard <quentin.gallard@digitalnolimit.com>
Co-authored-by: pb360playvid <prebid@360playvid.com>
Co-authored-by: mediayo <yehuda@mediayo.co>
Co-authored-by: Carlos Felix <carloshto@gmail.com>
Co-authored-by: rbstdev <devgit204@gmail.com>
Co-authored-by: Wenyuan Zhang <wzhang910@cable.comcast.com>
Co-authored-by: wenyuanzhang <wenyuanzhang@freewheel.tv>
Co-authored-by: Brian O'Kelley <bokelley@scope3.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Gabriel Gravel <ggravel@scope3.com>
Co-authored-by: Amit Biton <56631148+amitbiton01@users.noreply.github.com>
Co-authored-by: Shane Lacey <shanel262@hotmail.com>
Co-authored-by: Nick Llerandi <nick.llerandi@kargo.com>
Co-authored-by: Sebastien Boisvert <sebastien.boisvert@contxtful.com>
Co-authored-by: rufiange <sebastien@rufiange.com>
Co-authored-by: richardngo-consumable <rngo@consumable.com>
Co-authored-by: Karim Mourra <karim@jwplayer.com>
Co-authored-by: Joshua Tomlinson <og.ginger@gmail.com>
Co-authored-by: metax-kehan <115962296+metax-kehan@users.noreply.github.com>
Co-authored-by: Denis Logachov <ckbo3hrk@gmail.com>
Co-authored-by: Rafal Sieczka <rafal.sieczka@openx.com>
Co-authored-by: Dmitry Ermakov <dimurer@yandex-team.ru>
Co-authored-by: a.popov <60257866+allar15@users.noreply.github.com>
Co-authored-by: Marc-Enzo Bonnafon <marcenzo.bonnafon@gmail.com>
Co-authored-by: Olivier <osazos@adagio.io>
Co-authored-by: Jozef Bartek <31618107+jbartek25@users.noreply.github.com>
Co-authored-by: Appstock LTD <sdksupport@app-stock.com>
Co-authored-by: Kanceliarenko <kostiantyn.k@teqblaze.com>
Co-authored-by: teqblaze <162988436+teqblaze@users.noreply.github.com>
Co-authored-by: Simon Aebli <simon.aebli@goldbach.com>
Co-authored-by: Filip Stamenkovic <ficadub@gmail.com>
Co-authored-by: quietPusher <129727954+quietPusher@users.noreply.github.com>
Co-authored-by: Mikael Lundin <mikael-lundin@users.noreply.github.com>
Co-authored-by: BoldwinDev <sdk@bold-win.com>
Co-authored-by: Gabriel Gravel <gravelg@users.noreply.github.com>
Co-authored-by: Pubmatic-Supriya-Patil <131644110+Pubmatic-Supriya-Patil@users.noreply.github.com>
Co-authored-by: andreasgreen <andreas.green@gmail.com>
Co-authored-by: Alessandro Rosetti <alessandro.rosetti@gmail.com>
Co-authored-by: cto-clydo <cto@clydo.io>
Co-authored-by: Eugene Dorfman <eugene.dorfman@gmail.com>
Co-authored-by: postindustria-code <oss@postindustria.com>
pm-isha-bharti pushed a commit to PubMatic-OpenWrap/prebid-server that referenced this pull request Jan 2, 2026
* RTBHouse: PMP removal, publisherId parameter extraction (prebid#4564)

* Adnuntius: Pass targeting to ad server (prebid#4545)

* New Adapter: Boldwin Rapid (prebid#4478)

* Scope3: Various fixes to RTD module (prebid#4544)

* PubMatic: Pass alias bidder name through (prebid#4588)

* BidTheatre: Update endpoint and add redirect user sync (prebid#4562)

* CWire: Add userSync (prebid#4516)

* New Adapter: Clydo (prebid#4535)

* New Adapter: Microsoft (msft) (prebid#4592)

* Syncer: Allow Duplicate Syncer Key For Identical Config (prebid#4622)

* Adagio: Enable site capability (prebid#4590)

* Adagio: Remove hardcoded seat name (prebid#4596)

* Warn in auction response for bidders blocked by privacy settings (prebid#4537)

Co-authored-by: oleksandr <oleksandr@assertive.ai>

* Logging: Add interface with default glog implementation (prebid#4085)

Co-authored-by: postindustria-code <oss@postindustria.com>

* Post Upgrade Patch: Fix Test Cases

* Add Builder for Microsoft Bidder

---------

Co-authored-by: Piotr Jaworski <109736938+piotrj-rtbh@users.noreply.github.com>
Co-authored-by: Mikael Lundin <mikael-lundin@users.noreply.github.com>
Co-authored-by: BoldwinDev <sdk@bold-win.com>
Co-authored-by: Gabriel Gravel <gravelg@users.noreply.github.com>
Co-authored-by: Pubmatic-Supriya-Patil <131644110+Pubmatic-Supriya-Patil@users.noreply.github.com>
Co-authored-by: andreasgreen <andreas.green@gmail.com>
Co-authored-by: Alessandro Rosetti <alessandro.rosetti@gmail.com>
Co-authored-by: cto-clydo <cto@clydo.io>
Co-authored-by: Scott Kay <noreply@syntaxnode.com>
Co-authored-by: Olivier <osazos@adagio.io>
Co-authored-by: linux019 <anode.dev@gmail.com>
Co-authored-by: oleksandr <oleksandr@assertive.ai>
Co-authored-by: Eugene Dorfman <eugene.dorfman@gmail.com>
Co-authored-by: postindustria-code <oss@postindustria.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants