How to build a newsletter system from scratch
2024-09-13
We haven’t sent many announcements, marketing or notification emails. The only emails most customers would have received would be an account activation email and monthly invoices.
The reason for that is we didn’t have a good way to track customer preferences, nor did we want to share customer information with a third-party email service. Therefore, we set out to build our own. This post is a summary of how it works.
We decided to start with three separate newsletters:
monthly - general updates and announcements from the team. We’ll try to send one each month, but we’ll never send more than one a month.
maintenances - any kind of planned maintenance or unplanned outage information.
deals - offers and promotions. Pure marketing. Opt-in.
We’re thinking about implementing a fourth one called “audit” that would include significant account activity (logins, resource creation/destruction), but we need to do a bit more design thinking on that one first.
The first step is to provide a way for customers to self-manage their preferences. Doing this manually would be too time-consuming and error-prone, so we implemented a section in the customer portal that allows subscribing/unsubscribing at will. It’s easy to see what you’re subscribed to at any given time.
The second step is to ensure that all emails have a few key ingredients:
“unsubscribe” link that doesn’t require logging in and appears in plain text at the end of the email. This is required by the CAN-SPAM Act but it’s also good business practice. For us, this one unsubscribes a user from all lists.
List-Id header - this identifies which list the email belongs to. Some of our customers have sophisticated setups that file email according to their preferences. A List-Id header facilitates this.
List-Unsubscribe header - this allows unsubscribing to a particular list. It’s implemented as a mailto anchor that uses the same backend as the unsubscribe-all link.
The unsubscribe backend is pretty simple. All unsubscribe emails arrive at a dedicated email address. We only need to parse two fields: the from field and the subject field since the subject contains enough information to determine which (or all) lists to unsubscribe from. The process then updates the same preferences that the user has self-service access to in the portal.
We ended up rolling our own email sending infrastructure. In addition to the required ingredients mentioned above, our email tool queries subscribers for a certain list and forms an email with the desired content. We don’t do any kind of “merge” process to insert a name in the greeting–our experience is that most companies don’t do this very well, particularly when they send emails outside of their own country or native language, and “first name” isn’t specific information we ask of customers anyway.
If you have any ideas or feedback, get in touch!