From 3897d6fb7ed0d65d5996dc10277018af5e82b7bd Mon Sep 17 00:00:00 2001 From: Aadesh Patel Date: Mon, 20 Apr 2020 16:14:12 +0000 Subject: [PATCH] populate the app ID in the FAN timeout notif url with the publisher ID and the auction with the request ID --- .../audienceNetworktest/exemplary/banner.json | 6 ++-- .../exemplary/interstitial.json | 6 ++-- .../exemplary/native-1.1.json | 6 ++-- .../audienceNetworktest/exemplary/video.json | 6 ++-- .../supplemental/banner-format-only.json | 6 ++-- .../supplemental/multi-imp.json | 12 +++---- .../supplemental/no-bid-204.json | 4 +-- .../supplemental/split-placementId.json | 6 ++-- adapters/audienceNetwork/facebook.go | 32 +++++++++++++++++-- adapters/audienceNetwork/facebook_test.go | 22 +++++++++++-- 10 files changed, 74 insertions(+), 32 deletions(-) diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json index 632629b53a2..f5f92515e26 100644 --- a/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json +++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/banner.json @@ -51,7 +51,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -84,7 +84,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } @@ -92,7 +92,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-id", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json index 630e26d3f90..bad228d5f18 100644 --- a/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json +++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/interstitial.json @@ -52,7 +52,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -86,7 +86,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } @@ -94,7 +94,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-id", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json index 288c7c14e5d..9090d80d099 100644 --- a/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json +++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/native-1.1.json @@ -45,7 +45,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -78,7 +78,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } @@ -86,7 +86,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-id", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json b/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json index 15563c2ada5..22c62f8b821 100644 --- a/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json +++ b/adapters/audienceNetwork/audienceNetworktest/exemplary/video.json @@ -50,7 +50,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -88,7 +88,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } @@ -96,7 +96,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-id", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json index 52b7655593a..3edd6569258 100644 --- a/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json +++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/banner-format-only.json @@ -53,7 +53,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -86,7 +86,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } @@ -94,7 +94,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-id", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json index 0fe836af4de..16e8aede10c 100644 --- a/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json +++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/multi-imp.json @@ -70,7 +70,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-1", "imp": [ { "id": "test-imp-1", @@ -103,7 +103,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "dfecd103a45daeb2a01728afb8ce78f6738f6007ecfebe1ca616b196e22b43e9", "platformid": "test-platform-id" } } @@ -111,7 +111,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-1", "seatbid": [ { "bid": [ @@ -147,7 +147,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-2", "imp": [ { "id": "test-imp-2", @@ -180,7 +180,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "a5fead11a4db86d0f62f57c3d8001640227120c8ef236549f0db010c1dbab399", "platformid": "test-platform-id" } } @@ -188,7 +188,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-2", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json index 042c86bd7fd..bb192aad76f 100644 --- a/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json +++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/no-bid-204.json @@ -45,7 +45,7 @@ ] }, "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -78,7 +78,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } diff --git a/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json b/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json index b99834ab1df..4c561c55276 100644 --- a/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json +++ b/adapters/audienceNetwork/audienceNetworktest/supplemental/split-placementId.json @@ -39,7 +39,7 @@ "expectedRequest": { "uri": "https://an.facebook.com/placementbid.ortb", "body": { - "id": "test-req-id", + "id": "test-imp-id", "imp": [ { "id": "test-imp-id", @@ -72,7 +72,7 @@ }, "tmax": 500, "ext": { - "authentication_id": "b2f9edfd707106adb6b692520081ad7e2a345444af1a895310228297a1b6247e", + "authentication_id": "4e24a2b23fbfb5e41a9093b921d6cddf497c24dd5f63879038cec2ab2f27d174", "platformid": "test-platform-id" } } @@ -80,7 +80,7 @@ "mockResponse": { "status": 200, "body": { - "id": "test-req-id", + "id": "test-imp-id", "seatbid": [ { "bid": [ diff --git a/adapters/audienceNetwork/facebook.go b/adapters/audienceNetwork/facebook.go index db7657f59b7..9edb9a7d57e 100644 --- a/adapters/audienceNetwork/facebook.go +++ b/adapters/audienceNetwork/facebook.go @@ -130,6 +130,11 @@ func (this *FacebookAdapter) modifyRequest(out *openrtb.BidRequest) error { return err } + // Every outgoing FAN request has a single impression, so we can safely use the unique + // impression ID as the FAN request ID. We need to make sure that we update the request + // ID *BEFORE* we generate the auth ID since its a hash based on the request ID + out.ID = imp.ID + reqExt := facebookReqExt{ PlatformID: this.platformID, AuthID: this.makeAuthID(out), @@ -455,18 +460,39 @@ func NewFacebookBidder(client *http.Client, platformID string, appSecret string) } func (fa *FacebookAdapter) MakeTimeoutNotification(req *adapters.RequestData) (*adapters.RequestData, []error) { - // Note, facebook creates one request per imp, so all these requests will only have one imp in them - auction_id, err := jsonparser.GetString(req.Body, "imp", "[0]", "id") + var ( + rID string + pubID string + err error + ) + + // Note, the facebook adserver can only handle single impression requests, so we have to split multi-imp requests into + // multiple request. In order to ensure that every split request has a unique ID, the split request IDs are set to the + // corresponding imp's ID + rID, err = jsonparser.GetString(req.Body, "id") if err != nil { return &adapters.RequestData{}, []error{err} } - uri := fmt.Sprintf("https://www.facebook.com/audiencenetwork/nurl/?partner=%s&app=%s&auction=%s&ortb_loss_code=2", fa.platformID, fa.platformID, auction_id) + // The publisher ID is either in the app object or the site object, depending on the supply of the request so we need + // to check both + pubID, err = jsonparser.GetString(req.Body, "app", "publisher", "id") + if err != nil { + pubID, err = jsonparser.GetString(req.Body, "site", "publisher", "id") + if err != nil { + return &adapters.RequestData{}, []error{ + errors.New("path [app|site].publisher.id not found in the request"), + } + } + } + + uri := fmt.Sprintf("https://www.facebook.com/audiencenetwork/nurl/?partner=%s&app=%s&auction=%s&ortb_loss_code=2", fa.platformID, pubID, rID) timeoutReq := adapters.RequestData{ Method: "GET", Uri: uri, Body: nil, Headers: http.Header{}, } + return &timeoutReq, nil } diff --git a/adapters/audienceNetwork/facebook_test.go b/adapters/audienceNetwork/facebook_test.go index 1edaabd45d7..784a540e596 100644 --- a/adapters/audienceNetwork/facebook_test.go +++ b/adapters/audienceNetwork/facebook_test.go @@ -43,9 +43,9 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "audienceNetworktest", NewFacebookBidder(nil, "test-platform-id", "test-app-secret")) } -func TestMakeTimeoutNotice(t *testing.T) { +func TestMakeTimeoutNoticeApp(t *testing.T) { req := adapters.RequestData{ - Body: []byte(`{"imp":[{"id":"1234"}]}}`), + Body: []byte(`{"id":"1234","imp":[{"id":"1234"}],"app":{"publisher":{"id":"5678"}}}`), } fba := NewFacebookBidder(nil, "test-platform-id", "test-app-secret") @@ -56,9 +56,25 @@ func TestMakeTimeoutNotice(t *testing.T) { toReq, err := tb.MakeTimeoutNotification(&req) assert.Nil(t, err, "Facebook MakeTimeoutNotification() return an error %v", err) - expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=test-platform-id&auction=1234&ortb_loss_code=2" + expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=5678&auction=1234&ortb_loss_code=2" assert.Equal(t, expectedUri, toReq.Uri, "Facebook timeout notification not returning the expected URI.") +} +func TestMakeTimeoutNoticeSite(t *testing.T) { + req := adapters.RequestData{ + Body: []byte(`{"id":"1234","imp":[{"id":"1234"}],"site":{"publisher":{"id":"5678"}}}`), + } + fba := NewFacebookBidder(nil, "test-platform-id", "test-app-secret") + + tb, ok := fba.(adapters.TimeoutBidder) + if !ok { + t.Error("Facebook adapter is not a TimeoutAdapter") + } + + toReq, err := tb.MakeTimeoutNotification(&req) + assert.Nil(t, err, "Facebook MakeTimeoutNotification() return an error %v", err) + expectedUri := "https://www.facebook.com/audiencenetwork/nurl/?partner=test-platform-id&app=5678&auction=1234&ortb_loss_code=2" + assert.Equal(t, expectedUri, toReq.Uri, "Facebook timeout notification not returning the expected URI.") } func TestMakeTimeoutNoticeBadRequest(t *testing.T) {