Disclaimer
Just a small disclaimer, keep in mind that what we are going to build is nowhere as efficient as a proper mailing system like Listmonk or other paid alternatives. This is just a demonstration of what Directus is capable of, but it's a good start if you wish to dive deeper in building your own mailing system.
Planning our newsletter system
Before we begin, we have to think about the skeleton of our newsletter system which is composed of three important things:
- Contact list - the people who will receive our newsletter
- Campaigns - the mailings that will be sent to our contacts
- Automation - to send your campaigns to your contacts in one click
We need to define what are their purposes and how they will interact with each other
The newsletter contact list
As we said before, the contact list will contain a list of people that will receive our newsletter. Here's a simple structure for this:
- Email - unique string corresponding to the contact email
- Name (optional) - if you want to include the contact's name (for more proximity), you can also include depending on how you build your sign-up form
- Status (optional) - if you wish to save the contact's information after they unsubscribed from your newsletter, you can use this field to stop sending them newsletters and keep their information in your database instead of deleting the contact (of course check that you mention this information in your privacy policy)
The newsletter campaigns
This is where you will design your campaigns that will be sent to your contacts. Here's a simple structure for this:
- Name - the name of your campaign
- Subject - this is the title your client will see when they receive your e-mail
- Content - the content of your e-mail
Sending your campaigns
To send our campaigns, we will use Directus' Flows. We will create 3 flows:
- Trigger send campaign - this will be our entry point, it will parse the selected campaigns and run the second flow for each campaign
- Send newsletter campaign - the second flow that will get all the data needed to send our newsletter, parse our contact list and trigger the third flow for each contact in our list
- Send newsletter to contact - our final flow that will send the newsletter to each contact individually
So now that we have defined the structure of our system, let's build it.
Building the newsletter collections
Contact list collection
Create a collection named newsletter_contacts, add a unique field named email (and other fields if you want to) and you're good to go.
Newsletter campaigns collection
Create a collection named newsletter_campaigns and add the following fields:
- name - String
- subject - String
- content - Text (WYSIWYG or Markdown as you wish)
When everything is set-up, we can go forward and connect everything together.
Building the newsletter system
Now that our collections are created, we will use Flows to interact with them. First, create the three Flows mentioned above. When it's done, you can continue
The first Flow
This Flow will take an array of newsletter campaign ID, parse the list and trigger the second flow for each key in the array. It's a very simple Flow, set it up like this:
- Trigger type - Manual
- Collections - Newsletter Campaigns
- Asynchronous - Enabled
Then, add a Trigger Flow operation and set it up like this:
- Name - Send newsletter campaign
- Payload - "{{ $trigger.body.keys }}"
Explanation: "{{ $trigger.body.keys }}" is an array corresponding to the array of campaign IDs you select from the dashboard. When you pass an array as payload to another Flow, the latter will run for each element in the array.
The second Flow
This Flow will prepare and format all the datas needed to send our newsletter. Set it up like this:
- Name - Send newsletter campaign
- Trigger - Another Flow
- Response Body - All data
Then, add the following operations (following the order):
- Get campaign
- Type - Read Data
- Permission - Full access
- Collection - Newsletter Campaigns
- IDs - {{$trigger}}
- Get contacts
- Type - Read Data
- Permission - Full access
- Collection - Newsletter Contacts
- Query
{
"limit": -1
}
- Format newsletter data
- Type - Run Script
- Code
module.exports = async function(data) {
return data.get_contacts.map(res => ({...res, campaign: data.get_campaign}));
}
- Trigger Flow
- Type - Trigger Flow
- Flow - Send newsletter to contact
- Payload - "{{$last}}"
Explanation: we get information about the campaign that was passed from the previous Flow, then we get all our contacts, and we create an array composed of objects that have both the contacts and the campaign that we pass to our final Flow.
The third and final Flow
This is the last piece of the puzzle. Its purpose is to send the newsletter to our contacts and it's a pretty simple one:
- Name - Send newsletter to contact
- Type - Another Flow
- Response Body - All Data
Now, let's add the email sending operation:
- Operation Type - Send Email
- To - {{$trigger.email}}
- Subject - {{$trigger.campaign.subject}}
- Type - WYSIWYG or Markdown (as you wish)
- Body
// Your custom content (ex: <img src={LOGO_URL}/>)
{{$trigger.campaign.content}}
// Your custom content
Sending our newsletter campaigns
Now that everything is set-up, you can send your campaigns by selecting them from the collection page and clicking on the Trigger send campaign on the right sidebar, under the Flows section.
Conclusion
You have now built a (simple) working newsletter system. Don't hesitate to play around with it and add more features! You can for example add a CRON job to send your campaigns at a given time.
If you're still struggling with your Directus instance, get in touch for professional assistance.
Take care and if you have questions don't hesitate to comment!
Also built with Directus: