NextJS - newsletter API with Mailchimp

Sadat Jubayer

Sadat Jubayer

July 07, 2021

• 3 min read

On this site, I have created a Newsletter Subscribing system. I have used Mailchimp API, and made a serverless function to talk with that. In this article, I will guide you about this implementation process.

What you should know:

  • 💡 React and NextJS basics.
  • 💡 How API works.

Step one - Configuring Mailchimp

  • Signup on Mailchimp https://login.mailchimp.com/signup/

  • Collect your API key from Mailchimp > Account > Extras > API Keys > Create a Key.

  • Create an Audience from Mailchimp > Audience > All Contacts

  • Collect collection id from All Contacts > Settings > Audience name and campaign defaults > Audience ID

Now you have the followings:

  1. API key
  2. Audience ID

Step two - Setup Environment Variables

NextJS has built-in support for env. You need to create a .env.local file at the root of your project. Then paste your API key and Audience ID there like this

.env.local
MAILCHIMP_API_KEY=<Your API Key>
MAILCHIMP_LIST_ID=<Your Audience ID >

Step two - Create NextJS API

To create an API on NextJS, you need to create a file in the pages/api folder. I named I subscribe; you can name it whatever you like. The default function return from the file is the serverless function or API route.

pages/api/subscribe.js

Let's prepare a function that will prepare you the data you need to send to MailChimp.

function getRequestParams(email) {
    // Getting values form ENV
    const API_KEY = process.env.MAILCHIMP_API_KEY;
    const LIST_ID = process.env.MAILCHIMP_LIST_ID;

    // Getting Mailchimp datacenter
    const DATACENTER = process.env.MAILCHIMP_API_KEY.split('-')[1];

    //  Generating request URL as per as Mailchimp docs
    const url = `https://${DATACENTER}.api.mailchimp.com/3.0/lists/${LIST_ID}/members`;

    // Mailchimp data shape
    const data = {
        email_address: email,
        status: 'subscribed'
    };

    // Request Headers
    const headers = {
        'Content-Type': 'application/json',
        Authorization: `auth ${API_KEY}`
    };

    return {
        url,
        data,
        headers
    };
}

All data you need to talk with Mailchimp is ready. Let's create the API now. This API shape is like this -

  • Endpoint: '/api/subscibe'
  • Method: POST
  • Body: email
export default async (req, res) => {
    // Only post method allowed
    if (req.method !== 'POST') {
        res.setHeader('Allow', ['POST']);
        return res.status(405).json({
            message: 'Method is not allowed'
        });
    }

    const { email } = req.body;

    // Validation
    if (!email || !email.length) {
        return res.status(400).json({
            error: 'Forgot to add your email?'
        });
    }

    //Sending request with the params using axios
    try {
        const { url, data, headers } = getRequestParams(email);
        await axios.post(url, data, { headers });
        return res.status(201).json({ error: null });
    } catch (error) {
        return res.status(400).json({
            error: `Oops,  ${error?.response?.data?.detail}`
        });
    }
};

The final subscibe.js file is like this:

subscribe.js
import axios from 'axios';

function getRequestParams(email) {
    const API_KEY = process.env.MAILCHIMP_API_KEY;
    const LIST_ID = process.env.MAILCHIMP_LIST_ID;

    const DATACENTER = process.env.MAILCHIMP_API_KEY.split('-')[1];

    const url = `https://${DATACENTER}.api.mailchimp.com/3.0/lists/${LIST_ID}/members`;

    const data = {
        email_address: email,
        status: 'subscribed'
    };

    const headers = {
        'Content-Type': 'application/json',
        Authorization: `auth ${API_KEY}`
    };

    return {
        url,
        data,
        headers
    };
}

export default async (req, res) => {
    // Only post method allowed
    if (req.method !== 'POST') {
        res.setHeader('Allow', ['POST']);
        return res.status(405).json({
            message: 'Method is not allowed'
        });
    }

    const { email } = req.body;

    if (!email || !email.length) {
        return res.status(400).json({
            error: 'Forgot to add your email?'
        });
    }

    try {
        const { url, data, headers } = getRequestParams(email);
        await axios.post(url, data, { headers });
        return res.status(201).json({ error: null });
    } catch (error) {
        return res.status(400).json({
            error: `Oops,  ${error?.response?.data?.detail}`
        });
    }
};

References: