diff --git a/adapters/ix/ix.go b/adapters/ix/ix.go index 5e10138f8f3..b251ec0f736 100644 --- a/adapters/ix/ix.go +++ b/adapters/ix/ix.go @@ -7,7 +7,10 @@ import ( "fmt" "io/ioutil" "net/http" + "sort" + "github.com/mxmCherry/openrtb/v15/native1" + native1response "github.com/mxmCherry/openrtb/v15/native1/response" "github.com/mxmCherry/openrtb/v15/openrtb2" "github.com/prebid/prebid-server/adapters" "github.com/prebid/prebid-server/config" @@ -400,7 +403,7 @@ func (a *IxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReque for _, bid := range seatBid.Bid { bidType, ok := impMediaType[bid.ImpID] if !ok { - errs = append(errs, fmt.Errorf("Unmatched impression id: %s.", bid.ImpID)) + errs = append(errs, fmt.Errorf("unmatched impression id: %s", bid.ImpID)) } var bidExtVideo *openrtb_ext.ExtBidPrebidVideo @@ -417,6 +420,28 @@ func (a *IxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReque } } + var bidNative1v1 *Native11Wrapper + if bidType == openrtb_ext.BidTypeNative { + err := json.Unmarshal([]byte(bid.AdM), &bidNative1v1) + if err == nil && len(bidNative1v1.Native.EventTrackers) > 0 { + mergeNativeImpTrackers(&bidNative1v1.Native) + if json, err := json.Marshal(bidNative1v1); err == nil { + bid.AdM = string(json) + } + } + } + + var bidNative1v2 *native1response.Response + if bidType == openrtb_ext.BidTypeNative { + err := json.Unmarshal([]byte(bid.AdM), &bidNative1v2) + if err == nil && len(bidNative1v2.EventTrackers) > 0 { + mergeNativeImpTrackers(bidNative1v2) + if json, err := json.Marshal(bidNative1v2); err == nil { + bid.AdM = string(json) + } + } + } + bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{ Bid: &bid, BidType: bidType, @@ -444,3 +469,33 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters } return bidder, nil } + +// native 1.2 to 1.1 tracker compatibility handling + +type Native11Wrapper struct { + Native native1response.Response `json:"native,omitempty"` +} + +func mergeNativeImpTrackers(bidNative *native1response.Response) { + + // create unique list of imp pixels urls from `imptrackers` and `eventtrackers` + uniqueImpPixels := map[string]struct{}{} + for _, v := range bidNative.ImpTrackers { + uniqueImpPixels[v] = struct{}{} + } + + for _, v := range bidNative.EventTrackers { + if v.Event == native1.EventTypeImpression && v.Method == native1.EventTrackingMethodImage { + uniqueImpPixels[v.URL] = struct{}{} + } + } + + // rewrite `imptrackers` with new deduped list of imp pixels + bidNative.ImpTrackers = make([]string, 0) + for k := range uniqueImpPixels { + bidNative.ImpTrackers = append(bidNative.ImpTrackers, k) + } + + // sort so tests pass correctly + sort.Strings(bidNative.ImpTrackers) +} diff --git a/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json b/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json new file mode 100644 index 00000000000..36a239987a6 --- /dev/null +++ b/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json @@ -0,0 +1,104 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "http://host/endpoint", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"eventtrackers\":[{\"url\":\"https://example.com/imp-2.gif\",\"event\":1,\"method\":1},{\"url\":\"https://example.com/imp-3.gif\",\"event\":1,\"method\":1}],\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"]}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\",\"https://example.com/imp-3.gif\"],\"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"https://example.com/imp-2.gif\"},{\"event\":1,\"method\":1,\"url\":\"https://example.com/imp-3.gif\"}]}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/ix/ixtest/supplemental/bad-imp-id.json b/adapters/ix/ixtest/supplemental/bad-imp-id.json index 0b852c85d2b..1ca053b674e 100644 --- a/adapters/ix/ixtest/supplemental/bad-imp-id.json +++ b/adapters/ix/ixtest/supplemental/bad-imp-id.json @@ -111,7 +111,7 @@ ], "expectedMakeBidsErrors": [ { - "value": "Unmatched impression id: bad-imp-id.", + "value": "unmatched impression id: bad-imp-id", "comparison": "literal" } ] diff --git a/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json b/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json new file mode 100644 index 00000000000..4cf314e742f --- /dev/null +++ b/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json @@ -0,0 +1,104 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "http://host/endpoint", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"],\"eventtrackers\":[]}}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"],\"eventtrackers\":[]}}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json b/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json new file mode 100644 index 00000000000..d8c78a5cbca --- /dev/null +++ b/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json @@ -0,0 +1,104 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "http://host/endpoint", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"]}}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"native\":{\"assets\":[{\"id\":123,\"required\":1,\"title\":{\"text\":\"Learn about this awesome thing\"}},{\"id\":124,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/thumbnail1.png\"}},{\"id\":128,\"required\":1,\"img\":{\"url\":\"http://www.myads.com/largethumb1.png\"}},{\"id\":126,\"required\":1,\"data\":{\"value\":\"My Brand\"}},{\"id\":127,\"required\":1,\"data\":{\"value\":\"Learn all about this awesome story of someone using my product.\"}}],\"link\":{\"url\":\"http: //i.am.a/URL\"},\"imptrackers\":[\"https://example.com/imp-1.gif\",\"https://example.com/imp-2.gif\"]}}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/ix/ixtest/supplemental/native-missing.json b/adapters/ix/ixtest/supplemental/native-missing.json new file mode 100644 index 00000000000..ec2108ce5d1 --- /dev/null +++ b/adapters/ix/ixtest/supplemental/native-missing.json @@ -0,0 +1,104 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "http://host/endpoint", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + } + ] + } + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"native\":{}}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id", + "price": 0.5, + "adid": "29681110", + "adm": "{\"native\":{}}", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "cat": [ + "IAB3-1" + ], + "ext": { + "ix": {} + } + }, + "type": "native" + } + ] + } + ] +}