Statuses can get messy to manage when you use several notification providers. If you use, say, Slack, SendGrid, and Postmark, these integrations all have their own terminology and logic around statuses. Just figuring out how many customers received your message means interpreting and reconciling all those different statuses, which can be a headache.
That’s why we tackled this problem at Courier and developed universal statuses. While we’re constantly making improvements and updates, I wanted to share how statuses work today in Courier and some of the things we thought through while building a single source of truth across integration providers. I’ll also explain how we provide open tracking for emails and click-through tracking across all channels.
Our system maps all your providers’ statuses into clear and universal definitions. Of course, you can always drill down into the provider’s specific message, but this layer of abstraction in Courier simplifies the high-level picture for you. It also makes it very easy for you to change or add providers. Even if the underlying statuses change, your view in Courier will always remain consistent, and you won’t have to do any work deciphering a new vocabulary.
Statuses in Courier are straight-forward and simple to understand. Furthermore, they’re linear and only move in one direction. We’ll never skip a status or revert to an earlier status, so you can rest assured that you always know what the next status will be if things go well. Here is a basic state diagram for statuses in Courier, with green arrows representing success and red arrows representing an error; below, we’ll go into each of the states and state changes in detail.
This status means that you’ve indicated you would like to send a message with Courier, and Courier is in the process of performing some validation and contacting your integration provider (like SendGrid or Slack) to tell them to send the message. When the integration provider accepts the send request, we move to the Sent stage. Sometimes, for example if we don’t hear back from the provider, Courier will need to retry with exponential back-off—in which case the message will remain Queued, with information about retries added to the metadata. In certain other cases, Courier will move the message to the Undeliverable state.
A message can go from a Queued status to an Undeliverable status for the following reasons, which you can see in the Courier UI or query using our Messages API:
Filtered: The message was filtered out based on user preferences or rules set within Courier.
No channels: We had no channels through which to deliver this message. While the message can be filtered out at the top level, it can also be filtered out at the level of the channels because it doesn’t meet some conditions set by the channels.
No providers: The user did not specify which provider you wanted to use for the channel that you’re sending the message through.
Provider error: We tried to ask the integration provider to send your message, but they rejected our request for some reason (maybe the wrong API key was used, or the recipient’s phone number didn’t pass their validation). The provider’s error messages are stored in our logs so you can inspect them further.
Unpublished: We have a built-in versioning system in Courier and you need to hit publish on a template before you can queue it up for sending. If you see this error, that means you’re trying to send a message that hasn’t been published yet.
Unsubscribed: This means the recipient has indicated they do not want to receive this type of notification.
An Undeliverable status is not necessarily the end of the road for your message. Courier will continue to retry sending to the provider, so that if you fix the reason for the error, the message could move from Undeliverable to Sent.
A status of Sent means that Courier was successful in calling your integration, and the integration accepted the request and is now trying to deliver the message. When a Sent status turns into a Delivered status, this means you can celebrate: the message has actually reached the recipient’s email, Slack, phone, etc.
When a message moves from Sent to Undeliverable, it will always be due to a Provider error of some kind. Usually, this is because the recipient’s email inbox bounced the message, but it could be due to other reasons such as an invalid email address. Some channels like Slack don’t distinguish between sent and delivered since delivery is essentially guaranteed. In this case, retrying will depend on the provider instead of Courier. Because we support idempotent requests, you could always resend the same request to us if the provider doesn’t support automatic retries.
This status means that your message has successfully arrived (although it doesn’t tell you whether the recipient opened your message—more on that in a moment). Courier supports the Delivered status for almost all email providers. There are providers that don’t offer delivered as a status so there isn’t data we can offer in those cases, but we are adding full status support for every provider that we integrate with.
Of course, outside of tracking your email’s journey from Queued to Sent to Delivered, you will also want to know how many users actually opened your message and clicked on the links inside. These engagement metrics are key for data-driven email notifications. We do our own email tracking at Courier so that you don’t have to go looking for this data across multiple providers or worry about configuring it with your integration directly.
How does this work? When someone opens your email, a transparent GIF pings our system. (We’ve worked to make sure that opens won’t be counted when an email client “auto-opens” your emails, though it’s an imperfect science.) To track click-through rates, Courier generates a unique ID for each link in your email, so that when someone clicks on it, the query data sent back to Courier contains that ID and we can show you the breakdown of the click-through rates for links in your emails.
It probably goes without saying, but we’ll say it anyway: While other statuses will only appear once per message in a linear fashion, opens and clicks can appear multiple times, since the recipient might keep referring back to the email and its links. Courier will log the respective open or click each time this happens.
To access your statuses, simply go into your Event Logs in Courier. You can see the Status of your notifications as a column in the UI, and you can filter to show, for example, only your Undeliverable messages. When you click into one of the events, you can see more details about the status, including the message that was sent back to Courier by the downstream provider. If you’re trying to get into the data at scale, you’ll want to use our REST API endpoints—we’ll share more details on these in a future article. For some more insight into how logs work in Courier, check out the Courier Live I was on a few weeks ago with Aydrian.
To get acquainted with Courier’s Event Logs and a lot more (like how we give you easy templates and routing logic across email, push notifications, SMS, and Slack) this demo video is a great start. If you want to try Courier for yourself, you can sign up for free!
We have lots of exciting updates coming to our logging infrastructure, such as supporting webhooks and building advanced analytics on top of the data we’re collecting so stay tuned!