If you work at ActiveCampaign or know someone who works at ActiveCampaign please hook me up with them. I'd love to work on making their webhooks and documentation around it better. I think it would unlock a huge chunk of productivity.
This article goes over the hack needed to use a contact's field values
on a updateContact
webhook.
The scenario is pretty basic:
You use ActiveCampaign (AC) to send out a call to your backend server whenever a contact is being updated (i.e. using the updateContact webhook). On your backend you have some business logic as a function of the contact's fields and tags.
The body of updateContact has the following structure:
{
"type": "update",
"date_time": "2023-07-12T06:49:04-05:00",
"initiated_from": "admin",
"initiated_by": "admin",
"list": "0",
"contact": {
"id": "1234",
"email": "[email protected]",
"first_name": "Test",
"last_name": "User",
"phone": "+15555555555",
"ip": "10.0.6.48",
"tags": "month, free_forever, not_active_0912, TIER1, app_notif_reminder_sent, free-day-fix-1",
"fields": ["", "", "", "", "", "", "none", "Free Forever", "none", "", "none", "4", "", "", "2023-07-01", "2023-07-08", "2022-04-14", "+15555555555", "TIER1", "0", "Paid", "none"],
"customer_acct_name": "",
"orgname": ""
},
"customer_acct_name": "",
"customer_acct_id": "0",
"orgname": ""
}
There are two things that stand out as having been implemented in the wee hours of a hackathon: tags
and fields
.
tags
is a string of all the tags separated by a comma (,
). fields
is an array of strings, no matter the field's original data type. And more importantly, and what causes the headaches that probably brought you here, they are in a random order.
Now I'm not the sharpest tool in the... tool drawer, but that doesn't look like an optimal way to go about it.
If I was paid a Silicon Valley salary, I would've implemented tags
as an array of strings and fields
as a dictionary. But alas, I wasn't consulted and here we are.
The quick solution is to make a call to ActiveCampaign API to get the fields.
The call from the API returns an array of objects which you can parse to identify exactly which value belongs to which field.
So if before the process would look something like this:
- a change is made to a contact in AC
- AC sends out a webhook call
- your server processes the call
Now you need one more step:
- a change is made to a contact in AC
- AC sends out a webhook call
- your server makes a call to AC API endpoint && (a)waits for the response
- your server processes the result of both calls
That's the simple solution, if you can call it that.
The thing is that ActiveCampaign webhooks can send out 10-20 calls a second. And their API responds to 5 calls per second.
As the quote goes:
An API call for an API call makes both servers flood.
-- Abraham Lincoln
Ideally you would wait for all updateContact calls to finish then make just one call to AC API to get custom field values.
To do that, what I did was to add a few steps to the process described above and got to something like this.
- a change is made to a contact in AC
- AC sends out a webhook call
- your server processes the udpate call without the fields and marks the contact as needing to be updated
- run a function every X minutes (cron job) to make the AC API call for each user marked for update
Even though this means another write to the DB, another function/job running periodically, it's still cheaper than running an API call for every call from the AC webhook.