I've done this before with Mailchimp—automated daily newsletter reports that give everyone transparency on how emails performed. But Omeda is a different animal. Their reporting interface isn't excellent, and manually looking up newsletter performance meant logging in, finding each deployment, and pulling stats one by one. With multiple newsletters going out daily, that's a lot of clicking around.

So I built a bot that does it automatically. Every day at 5 pm, it hits Omeda's API, grabs all the deployments that went out, and posts a formatted report to our Slack channel. Now the entire company can see exactly how our newsletters performed—open rates, click rates, unsubscribes, the whole picture.

Here's what we'll be using to build this:

  1. Firebase Functions, to run our scheduled job and handle the automation

  2. Omeda API, to get deployment data

  3. Slack Web API, to post formatted messages to our channel

  4. Moment.js and moment-timezone, because timezones suck

  5. Axios, to make our HTTP requests

The Setup

Omeda API Credentials

First, you'll need to get your Omeda API key. You have to submit a support ticket to Omeda, wait for their response, and they'll eventually provide you with an API key. There's no self-service portal. Plan accordingly.

Once you have your key, you’ll also need the URL. Store both of these as environment variables; never hardcode API keys. We’re not trying to get hacked.

Slack Bot Configuration

For Slack, you’ll need to create a Slack App with chat:write permissions and install it in your workspace. Get your bot token from the OAuth section. You’ll also need your channel ID where you want these reports posted.

Firebase Setup

If you haven't set up Firebase Functions yet, you'll need to initialize a project and install the dependencies. We're using Firebase's v2 scheduler functions because they give us better control over timing and error handling.

The Core Function

The primary function is a scheduled job that runs every weekday at 5 pm Central. It's simple in concept: get today's date, search for emails sent today, pull their deployment data, format it for Slack, and post it.

I used Firebase's onSchedule instead of the older pubsub functions, because the error handling is better and the syntax is cleaner. The schedule runs Monday through Friday only—no point checking on weekends when newsletters don't go out.

Searching for Deployments

The first real piece is searching Omeda for deployments sent today. We're posting to Omeda's search endpoint with parameters for today's date and filtering to newsletters that have already been sent. The API returns an array of deployment objects, each with a URL field pointing to the complete deployment data.

Here's where Omeda's documentation gets frustrating. The endpoint structure is clear enough, but there are zero JavaScript examples. You have to figure out the header format yourself. That x-omeda-appid header? Not mentioned in their getting started guide. I wasted hours on authentication errors before I figured out the exact header name they expect.

The search parameters let you filter by deployment designation (we only want "Newsletter" types), status (we only want "SENT_OR_SENDING"), and date range. I set the number of results to 100 to make sure we catch everything, even on busy days.

Getting Deployment Stats

Once we have the URLs for today's deployments, we need to hit each one to get the actual stats. This is where things get interesting. I deliberately used a sequential loop instead of firing off all the requests at once with Promise.all(). Omeda's docs don't specify rate limits, and I didn't want to risk getting throttled or banned.

For each deployment, we pull the recipient count, unique opens, unique clicks, and unsubscribes. Then we calculate the rates: open rate (unique opens/recipients), click rate (unique clicks / unique opens), and unsubscribe rate (unsubscribes/recipients).

The subject line and sender name are buried in something called the Splits array. This makes sense once you know it—Omeda supports A/B testing with split deployments—but it's not immediately apparent from the API response structure. The subject line you care about is in the first element of that array.

Formatting for Slack

Slack's Block Kit API is how we make the messages look good. Each newsletter gets its own section with all the relevant stats formatted in a readable way. The blocks include a header with today's date, then a section for each newsletter with the subject line, sender, send date, and all the performance metrics.

The formatting makes it easy to scan and compare performance across different newsletters. We typically send 2-4 newsletters per day, so having them all in one message with consistent formatting is crucial.

Error Handling

I added validation at every step because Omeda's API doesn't always return data in the format you expect. We check whether deployments exist in the search response, validate that each deployment has the required data structure, and log warnings when something looks off. The function continues even if one deployment fails to parse—better to post a partial report than no report at all.

The Gotchas

Omeda's Documentation: The documentation is clear about what endpoints exist and what parameters they accept. But there are zero JavaScript examples. None. You have to figure out the header format yourself. If you're working with Omeda's API, expect to do some trial and error.

API Key Process: You can't just sign up and get an API key. You have to submit a support ticket and wait. Plan for this in your timeline.

The Splits Array: The subject line and sender name are buried in the first element of the Splits array. This makes sense once you know it (Omeda supports A/B testing with split deployments), but it's not immediately apparent from the API response structure.

Rate Limiting: I went with sequential requests rather than concurrent to avoid potential rate-limiting issues. Omeda's docs don't specify rate limits, so better safe than sorry.

Date Formatting: Omeda expects dates in a specific format, and their timezone handling isn't excellent. Using moment-timezone to handle all date formatting saved me from a bunch of off-by-one-day bugs.

Conclusion

Now, our entire company receives a Slack message every day at 5 pm with complete transparency into how our newsletters performed. We typically send 2-4 newsletters per day, and everyone can see the open rates, click rates, and engagement without logging into Omeda's interface.

The team didn't know they needed this until they had it. Now they check it every day.

Want the complete code?

This post covered the approach and architecture, but the actual implementation has a bunch of nuances—error handling, data validation, Slack formatting, and all the API quirks I figured out the hard way.

Sign up for the Automation Almanac newsletter and get the complete working code sent to your inbox. You'll get the full Firebase function, all the utility modules, and the exact Slack Block Kit formatting that makes these reports look great.

Subscribe to keep reading

This content is free, but you must be subscribed to Automation Almanac to continue reading.

Already a subscriber?Sign in.Not now