github.com/prebid/prebid-server/v2@v2.18.0/adapters/yieldmo/yieldmo.go (about) 1 package yieldmo 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v20/openrtb2" 9 "github.com/prebid/prebid-server/v2/adapters" 10 "github.com/prebid/prebid-server/v2/config" 11 "github.com/prebid/prebid-server/v2/errortypes" 12 "github.com/prebid/prebid-server/v2/openrtb_ext" 13 ) 14 15 type YieldmoAdapter struct { 16 endpoint string 17 } 18 19 type ExtImpBidderYieldmo struct { 20 adapters.ExtImpBidder 21 Data *ExtData `json:"data,omitempty"` 22 } 23 24 type ExtData struct { 25 PbAdslot string `json:"pbadslot"` 26 } 27 28 type Ext struct { 29 PlacementId string `json:"placement_id"` 30 Gpid string `json:"gpid,omitempty"` 31 } 32 33 type ExtBid struct { 34 MediaType string `json:"mediatype,omitempty"` 35 } 36 37 func (a *YieldmoAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 38 reqData, errors := a.makeRequest(request) 39 return []*adapters.RequestData{reqData}, errors 40 } 41 42 func (a *YieldmoAdapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, []error) { 43 var errs []error 44 45 if err := preprocess(request); err != nil { 46 errs = append(errs, err) 47 } 48 49 // Last Step 50 reqJSON, err := json.Marshal(request) 51 if err != nil { 52 errs = append(errs, err) 53 return nil, errs 54 } 55 56 headers := http.Header{} 57 headers.Add("Content-Type", "application/json;charset=utf-8") 58 59 return &adapters.RequestData{ 60 Method: "POST", 61 Uri: a.endpoint, 62 Body: reqJSON, 63 Headers: headers, 64 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 65 }, errs 66 } 67 68 // Mutate the request to get it ready to send to yieldmo. 69 func preprocess(request *openrtb2.BidRequest) error { 70 for i := 0; i < len(request.Imp); i++ { 71 var imp = request.Imp[i] 72 var bidderExt ExtImpBidderYieldmo 73 74 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 75 return &errortypes.BadInput{ 76 Message: err.Error(), 77 } 78 } 79 80 var yieldmoExt openrtb_ext.ExtImpYieldmo 81 82 if err := json.Unmarshal(bidderExt.Bidder, &yieldmoExt); err != nil { 83 return &errortypes.BadInput{ 84 Message: err.Error(), 85 } 86 } 87 88 var impExt Ext 89 impExt.PlacementId = yieldmoExt.PlacementId 90 91 if bidderExt.Data != nil { 92 if bidderExt.Data.PbAdslot != "" { 93 impExt.Gpid = bidderExt.Data.PbAdslot 94 } 95 } 96 97 impExtJSON, err := json.Marshal(impExt) 98 if err != nil { 99 return &errortypes.BadInput{ 100 Message: err.Error(), 101 } 102 } 103 104 request.Imp[i].Ext = impExtJSON 105 } 106 107 return nil 108 } 109 110 // MakeBids make the bids for the bid response. 111 func (a *YieldmoAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 112 if response.StatusCode == http.StatusNoContent { 113 return nil, nil 114 } 115 116 if response.StatusCode == http.StatusBadRequest { 117 return nil, []error{&errortypes.BadInput{ 118 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 119 }} 120 } 121 122 if response.StatusCode != http.StatusOK { 123 return nil, []error{&errortypes.BadServerResponse{ 124 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 125 }} 126 } 127 128 var bidResp openrtb2.BidResponse 129 130 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 131 return nil, []error{err} 132 } 133 134 bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) 135 136 for _, sb := range bidResp.SeatBid { 137 for i := range sb.Bid { 138 bidType, err := getMediaTypeForImp(sb.Bid[i]) 139 if err != nil { 140 continue 141 } 142 143 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 144 Bid: &sb.Bid[i], 145 BidType: bidType, 146 }) 147 } 148 } 149 return bidResponse, nil 150 } 151 152 // Builder builds a new instance of the Yieldmo adapter for the given bidder with the given config. 153 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 154 bidder := &YieldmoAdapter{ 155 endpoint: config.Endpoint, 156 } 157 return bidder, nil 158 } 159 160 // Retrieve the media type corresponding to the bid from the bid.ext object 161 func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) { 162 var bidExt ExtBid 163 if err := json.Unmarshal(bid.Ext, &bidExt); err != nil { 164 return "", &errortypes.BadInput{Message: err.Error()} 165 } 166 167 switch bidExt.MediaType { 168 case "banner": 169 return openrtb_ext.BidTypeBanner, nil 170 case "video": 171 return openrtb_ext.BidTypeVideo, nil 172 case "native": 173 return openrtb_ext.BidTypeNative, nil 174 default: 175 return "", fmt.Errorf("invalid BidType: %s", bidExt.MediaType) 176 } 177 }