Synchronize Audience Data with Webhooks

At a glance

Webhooks are a helpful tool that you can use to collect information about audience changes in Mailchimp as they happen. By entering a valid URL that’s set up to accept HTTP POST requests, you can receive updates on subscriptions, changed email addresses, campaign sending, and more.  

You can use webhooks to:

  • Alert your application when a campaign has finished sending

  • Keep your client’s profile data in sync with your own database

  • Detect when an email address starts bouncing

For the purposes of this guide, we run a messaging app for vegetarians called Chatatouille. We use Mailchimp for our marketing emails, and we want to keep our application’s database in sync with our Mailchimp audience data. We’ll create a webhook that updates our database every time a user subscribes or unsubscribes from our mailing list.

What you’ll need

  • A Mailchimp account

  • An audience you would like to use a webhook with

  • A callback URL for your application that can accept HTTP POST requests

  • Your API key and server prefix

Set up your callback URL

In order to create our webhook, we need to provide a callback URL that accepts HTTP POST requests. In the sample code below, you’ll see an example of what your application code might look like, but if you just want to test out a webhook to see what the payloads look like without setting up and deploying the webhook handler in your application, you can also use a service like RequestBin to stand up a callback URL without deploying anything.

When a webhook triggers based on your configured settings, Mailchimp sends an HTTP POST request to the URL you specified. If the URL is unavailable or takes more than 10 seconds to respond, the request is canceled and the system will try again later. Retries happen at increasing intervals over the course of 75 minutes. Excessive or unresponsive webhook requests may be dropped or disabled at Mailchimp’s discretion.

Note: Mailchimp strongly recommends using an HTTPS URL as your webhook callback URL. You can further increase the security of your webhook setup by using a URL containing a hard-to-guess secret and by checking this secret in your callback code.

Create a new webhook

There are two ways to set up our webhook: in the Mailchimp web app, or through the API. In this guide, we’ll walk through setting it up using the Mailchimp app.

To create a webhook: 

  1. Log into Mailchimp and navigate to the Audience page

  2. Select the audience you want to work with in the the Current Audience dropdown

  3. Click the Manage Audience dropdown button and select Settings

  4. On the Settings page, click Webhooks

  5. Click the Create New Webhook button

  6. In the Callback URL field, add the URL of the integration or application where you want to send webhook requests — this URL will receive data about your Mailchimp audience

  7. Select the boxes next to each update type to choose the events that will trigger your webhook — in this guide, we’ll choose Subscribes and Unsubscribes

  8. Click Save to save your new webhook

The webhook will now notify your application of subscribe and unsubscribe events as they occur.

Handling the webhook response in your application

Now that we have the webhook set up to alert us to changes in subscription status, we need to handle the callback data in our application. (This code should be accessible via the webhook URL you set up previously.)

The body of the webhook request is sent as application/x-www-form-urlencoded data. The Subscribes event, ingested and parsed as JSON, will look something like this: 

Response

JSON
{
  "type": "subscribe",
  "fired_at": "2009-03-26 21:35:57",
  "data": {
    "id": "8a25ff1d98",
    "list_id": "a6b5da1054",
    "email": "api@mailchimp.com",
    "email_type": "html",
    "ip_opt": "10.20.10.30",
    "ip_signup": "10.20.10.30"
    "merges": {
      "EMAIL": "api@mailchimp.com",
      "FNAME": "Mailchimp",
      "LNAME": "API",
      "INTERESTS": "Group1,Group2"
    }
  }
}

The body of the webhook request for the Unsubscribes event, ingested and parsed as JSON, will look something like this:

Response

JSON
{
  "type": "unsubscribe",
  "fired_at": "2009-03-26 21:40:57",
  "data": {
    "action": "unsub",
    "reason": "manual",
    "id": "8a25ff1d98",
    "list_id": "a6b5da1054",
    "email": "api+unsub@mailchimp.com",
    "email_type": "html",
    "ip_opt": "10.20.10.30",
    "campaign_id": "cb398d21d2",
    "merges": {
      "EMAIL": "api+unsub@mailchimp.com",
      "FNAME": "Mailchimp",
      "LNAME": "API",
      "INTERESTS": "Group1,Group2"
    }
  }
}

Now that we know what the webhook data will look like, we’ll write the code that will handle it on our server. For the purposes of this example, imagine that fakeDB is a package with functions we use to interact with Chatatouille’s database.

The code could look something like this:

Handling the webhook response in your application

const express = require("express");
const bodyParser = require("body-parser");
// this is a stand-in for the code you'd use to write to your own database
const fakeDB = require("fakeDB");

const app = express();

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));

app.post("/", (req, res) => {
 const { type, data } = req.body;
 if (type === "subscribe") {
   fakeDB.subscribeUser(data);
 } else if (type === "unsubscribe") {
   fakeDB.unsubscribeUser(data.id);
 }
});

app.listen(port, () =>
 console.log(`Listening at http://localhost:3000`)
);

Test the webhook

Now that we have the code set up, we’ll test it using the Mailchimp app:

  1. Go to the Audience page and select the audience you’d like to add a test member to

  2. In the Add Contacts dropdown, select Add a Subscriber

  3. Fill in the input fields with information for your test email account

  4. Check the checkbox for “This person gave me permission to email them” if you’d like to skip the step of confirming the subscription manually

  5. Hit Subscribe

  6. Your server should receive the webhook request and your database should be updated accordingly

If everything’s working, your webhook is good to go!