diff --git a/anymail/webhooks/sendinblue.py b/anymail/webhooks/sendinblue.py index 0fd63ba9..6cdd4350 100644 --- a/anymail/webhooks/sendinblue.py +++ b/anymail/webhooks/sendinblue.py @@ -56,7 +56,7 @@ def parse_events(self, request): "unsubscribe": (EventType.UNSUBSCRIBED, None), # shouldn't occur for transactional messages: "list_addition": (EventType.SUBSCRIBED, None), - "unique_opened": (EventType.OPENED, None), # you'll *also* receive an "opened" + "unique_opened": (EventType.OPENED, None), # first open; see also opened above } def esp_to_anymail_event(self, esp_event): diff --git a/docs/esps/brevo.rst b/docs/esps/brevo.rst index 4f4ebb2e..6934c251 100644 --- a/docs/esps/brevo.rst +++ b/docs/esps/brevo.rst @@ -264,10 +264,13 @@ Be sure to select the checkboxes for all the event types you want to receive. (A sure you are in the "Transactional" section of their site; Brevo has a separate set of "Campaign" webhooks, which don't apply to messages sent through Anymail.) -If you are interested in tracking opens, note that Brevo has both a "First opening" -and an "Opened" event type, and will generate both the first time a message is opened. -Anymail normalizes both of these events to "opened." To avoid double counting, you should -only enable one of the two. +If you are interested in tracking opens, note that Brevo has both "First opening" +and an "Known open" event types. The latter seems to be generated only for the second +and subsequent opens. Anymail normalizes both types to "opened." To track unique opens +enable only "First opening," or to track all message opens enable both. (Brevo used to +deliver both events for the first open, so be sure to check their current behavior +if duplicate first open events might cause problems for you. You might be able to use +the event timestamp to de-dupe.) Brevo will report these Anymail :attr:`~anymail.signals.AnymailTrackingEvent.event_type`\s: queued, rejected, bounced, deferred, delivered, opened (see note above), clicked, complained, diff --git a/tests/test_sendinblue_webhooks.py b/tests/test_sendinblue_webhooks.py index ce02651b..a2b224c6 100644 --- a/tests/test_sendinblue_webhooks.py +++ b/tests/test_sendinblue_webhooks.py @@ -294,8 +294,9 @@ def test_deferred_event(self): ) def test_opened_event(self): - # SendinBlue delivers unique_opened *and* opened on the first open. To avoid - # double-counting, you should only enable one of the two events in SendinBlue. + # SendinBlue delivers 'unique_opened' only on the first open, and 'opened' + # only on the second or later tracking pixel views. (But they used to deliver + # both on the first open.) raw_event = { "event": "opened", "email": "recipient@example.com", @@ -319,8 +320,7 @@ def test_opened_event(self): self.assertIsNone(event.user_agent) # SendinBlue doesn't report user agent def test_unique_opened_event(self): - # SendinBlue delivers unique_opened *and* opened on the first open. To avoid - # double-counting, you should only enable one of the two events in SendinBlue. + # See note in test_opened_event above raw_event = { "event": "unique_opened", "email": "recipient@example.com",