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

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:

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: