Revue - Sendy sync: Sendy calls

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
No comments yet. Be the first to comment.
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

Now that we have access to our Revue data, we can start processing it on Sendy.
In this article, I want to go over the two data sets we created in the previous article (unsubscribed users and subscribed users) and add/remove them from Sendy.
If you'd like to code with me, this is the starting point code for today.
In the previous article, we already set up the project and dependencies to leverage those things for this one.
However, when we queried Sendy's API via our API platform, we learned that we'd need the following keys.
Once you have retrieved these, add them to the .env file.
REVUE_API_TOKEN={YOUR_TOKEN}
SENDY_API_KEY={YOUR_TOKEN}
SENDY_LIST={LIST_ID}
The first thing we want to be able to do is unsubscribe users.
Let's start with one item we get from Revue as an example.
[
{
"id": 999999,
"list_id": 305882,
"email": "[email protected]",
"first_name": null,
"last_name": null,
"last_changed": "2022-01-08T04:30:04.492Z"
}
]
From this, we only need the email address.
For calling the Sendy API, we also learned we have to use form data to set the data attributes we want to POST.
Let's create a helper function that accepts an array and turns it into form data we can use.
Note: You can use the
form-datapackage, but I prefer native solutions as seen below
const convertToFormData = (data) => {
const formData = new URLSearchParams();
Object.keys(data).forEach((key) => {
formData.set(key, data[key]);
});
return formData;
};
This function transforms an object by getting the keys from it and setting it as URL search parameters. These can be used as form data.
We can use this function like this:
const data = {
api_key: 'test',
key1: 'testing',
};
console.log(convertToFormData(data));
// URLSearchParams { 'api_key' => 'test', 'key1' => 'testing' }
Then we can go ahead and define a function that can call the Sendy API. We can globalize this function again so we can re-use it easily.
const callSendyAPI = async (endpoint, body) => {
const response = await fetch(`https://sendy.daily-dev-tips.com/${endpoint}`, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
body,
}).then((res) => res.status);
return response;
};
Compared to Revue, the main difference with this one is that we use the POST method.
We also set the content type to accept and pass the form data.
Let's call this function, but before we do, we can create a default object with data we always have to send to Sendy. (API key and List id)
const sendyDefaults = {
api_key: process.env.SENDY_API_KEY,
list: process.env.SENDY_LIST,
};
To call the function, we can call it from our primary function.
(async () => {
const unsubscribeSendy = await callSendyAPI(
'/unsubscribe',
convertToFormData({
...sendyDefaults,
email: '[email protected]',
})
);
console.log(unsubscribeSendy);
})();
As you can see, we use the spread operator to use our default and add the email property to it.
We only get the status code when running this code, as the response is plain text.
However, when looking at my Sendy installation, I can see the action coming through!

We know the unsubscribe works, so now we can combine the two and loop over our revue unsubscribes to send this request to Sendy.
(async () => {
const revueUnsubscribed = await callRevueAPI('subscribers/unsubscribed');
for (const unsubscriber of revueUnsubscribed) {
const unsubscribeSendy = await callSendyAPI(
'/unsubscribe',
convertToFormData({
...sendyDefaults,
email: unsubscriber.email,
})
);
console.log(unsubscribeSendy);
}
})();
This code will loop over our unsubscribed Revue users and unsubscribe them in Sendy.
The main benefit of the integration we are building is that people can sign up via Revue and automatically get added to our Sendy newsletter.
To achieve this, we can use a similar approach as the unsubscribe but simply pass some other fields.
const subscribeSendy = await callSendyAPI(
'/subscribe',
convertToFormData({
...sendyDefaults,
email: '[email protected]',
silent: true,
})
);
console.log(subscribeSendy);
On execution, we should get a 200 code; if we look in Sendy, the user should be subscribed.

Let's finish it by looping over all the people in Revue who subscribed and adding them to Sendy.
Note: This script will handle try and subscribe people every time. We currently don't check if they are already in the system.
(async () => {
const revueSubscribed = await callRevueAPI('subscribers');
for (const subscriber of revueSubscribed) {
const subscribeSendy = await callSendyAPI(
'/subscribe',
convertToFormData({
...sendyDefaults,
email: subscriber.email,
silent: true,
})
);
console.log(subscribeSendy);
}
})();
And that's it. Running this code will add all your Revue subscribers to Sendy.
Note: You might want to wait and do an import into Revue first to sync the existing subscribers both ways.
You can find the code for this article on GitHub.
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter