DEV Community

Cover image for Newsletter with Next.js | Nextjs Mailchimp API Integration✉️
Bro Karim
Bro Karim

Posted on • Edited on

Newsletter with Next.js | Nextjs Mailchimp API Integration✉️

Introduction

Do you feel like your email inbox is too empty and needs a little useful 'spam'?

No worries—let’s fix it with some good old-fashioned email magic! Today, we’ll dive into setting up a Mailchimp newsletter subscription in your Next.js app

Why Mailchimp

Well, let's dive into the world of email marketing without emptying our wallets, shall we? Mailchimp's free tier perfect for us newsletter newbies who aren't ready to break the bank.
But wait....

there's more! Mailchimp isn't just a pretty face with a cute monkey logo. It's got a flexible API that's letting you bend and twist your newsletter form to your heart's content. And let's not forget its popularity among developers , which means when you're stuck, you're never alone. So, whether you're a penny-pinching startup or a customization enthusiast, Mailchimp's got your back.

Project Setup

Before we begin,I just want to say that you can get the full code in my GitHub repo.

1. Setting Up Mailchimp

To begin, you'll need to set up a Mailchimp account and obtain the necessary credentials

After creating your account, it's time to grab your API keys. If you're a seasoned pro with API keys, you can jump straight to the keys section. For the rest of us mere mortals, there's a handy guide to walk you through it.

Once you're on the API keys page, look for the "Create A Key" button. When naming your key, get creative but practical. Think of it as naming a pet rock – make it memorable and relevant, like "blog-newsletter-signup". This way, you won't scratch your head later wondering what on earth that key was for. Remember, a well-named API key is a happy API key!

Image description

Once, you’ve created a key, copy it and put it somewhere safe so you can use it later.

Next, you need a way to add a user to your audience when they hit the subscribe button on your form.

With your account set up, your API key, Audience ID, and API server region you are ready to get into coding up your newsletter. Let’s start by creating some environment variables.

2. Configuring Environment Variables for Mailchimp API

To keep your audience id and API keys secure, it's recommended to create environment variables. Otherwise, someone could see your keys and Audience ID in the request data.

To create environmental variables you need to create a .env file in the root directory of your project. This lets you access these values without hardcoding them to your form.

MAILCHIMP_API_KEY=xxxxxx-us20
MAILCHIMP_API_SERVER=us20
MAILCHIMP_AUDIENCE_ID=xxxxxx
Enter fullscreen mode Exit fullscreen mode

Remember to add .env to your .gitignore file to keep your credentials secure.

3. Creating API Route for Newsletter Subscription

Next, create an API route to handle the subscription process. This route will communicate with the Mailchimp API to add new subscribers. Create a file named app/api/subscribe/route.ts, Here how my file look like :

Image description

Now lets make a request to Mailchimp. You can achieve this by using Nextjs API routes with the following code :

import type { NextApiResponse } from 'next';
import { NextResponse } from 'next/server';

export async function POST(req: Request, res: NextApiResponse) {
  try {
    const { email } = await req.json();

    if (!email) {
      return res.status(400).json({ error: 'Email is required' });
    }

    const MailchimpKey = process.env.MAILCHIMP_API_KEY;
    const MailchimpServer = process.env.MAILCHIMP_API_SERVER;
    const MailchimpAudience = process.env.MAILCHIMP_LIST_ID;

    if (!MailchimpKey || !MailchimpServer || !MailchimpAudience) {
      throw new Error('Missing Mailchimp environment variables');
    }

    const customUrl = `https://${MailchimpServer}.api.mailchimp.com/3.0/lists/${MailchimpAudience}/members`;

    const response = await fetch(customUrl, {
      method: 'POST',
      headers: {
        Authorization: `Basic ${Buffer.from(`anystring:${MailchimpKey}`).toString('base64')}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email_address: email,
        status: 'subscribed',
      }),
    });

    if (!response.ok) {
      const errorData = await response.json();
      return res.status(response.status).json({ error: errorData.detail });
    }

    const received = await response.json();
    return NextResponse.json(received);
  } catch (error) {
    console.error('Error:', error);
    return res.status(500).json({ error: 'Internal Server Error' });
  }
}

Enter fullscreen mode Exit fullscreen mode

This API route receives the email address, validates it, and sends a request to Mailchimp to add the subscriber.

4. Creating a Newsletter Subscribe form

Finally, let's create a user-friendly subscription form using Formik for form handling and Yup for validation. Here's an example of how to implement the form:

"use client";

import React, { useState, useRef, useEffect } from "react";
import * as Yup from "yup";
import { Formik, Form, Field, ErrorMessage } from "formik";

type Props = {};

const requiredSchema = Yup.object({
  email: Yup.string().email("Invalid email").required("Email is required"),
});

function SubscribeForm({}: Props) {
  const [status, setStatus] = useState<number | null>(null);
  const [message, setMessage] = useState<string>("");
  const [buttonDisabled, setButtonDisabled] = useState<boolean>(false);
  const [submitting, setSubmitting] = useState<boolean>(false);
  const [run, setRun] = useState<boolean>(false);
  const [totalCounts, setTotalCounts] = useState<number>(400);
  const [dimensions, setDimensions] = useState({
    width: 0,
    height: 0,
  });

  useEffect(() => {
    const { innerWidth: width, innerHeight: height } = window;
    setDimensions({
      width,
      height,
    });
  }, []);
  return (
    <div className="flex flex-col space-y-8 md:w-[500px]">
      <Formik
        initialValues={{
          email: "",
        }}
        validationSchema={requiredSchema}
        onSubmit={async (values, { resetForm }) => {
          setButtonDisabled(true);
          try {
            const response = await fetch("/api/subscribe", {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                email: values?.email,
              }),
            });
            const datas = await response.json();
            if (datas.status >= 400) {
              setStatus(datas.status);
              setMessage("Error joining the newsletter. You can directly contact me at github@ebraj.");
              setTimeout(() => {
                setMessage("");
                setButtonDisabled(false);
              }, 2000);
              return;
            }

            setStatus(201);
            setMessage("Thank you for subscribing my newsletter 👻.");
            setRun(true);
            setTimeout(() => {
              setTotalCounts(0);
              setMessage("");
              resetForm();
              setButtonDisabled(false);
            }, 4000);
            setTotalCounts(400);
          } catch (error) {
            setStatus(500);
            setMessage("Error joining the newsletter. You can directly contact me at github@ebraj.");
            setTimeout(() => {
              setMessage("");
              setButtonDisabled(false);
            }, 2000);
          }
        }}
      >
        <Form className="w-full">
          <div className="w-full bg-transparent border flex-1 border-black rounded-full flex gap-2 px-3">
            <Field type="email" name="email" className="w-full grow rounded-md bg-transparent px-5 py-3 outline-none" placeholder="Enter your email" autoComplete="off" />
            <button className="rounded-full bg-black  my-2 px-4 py-2 font-bold text-gray-100 transition-all hover:scale-105 hover:bg-gray-900 disabled:opacity-80" type="submit" disabled={buttonDisabled}>
              {submitting ? "Submitting" : "Subscribe"}
            </button>
          </div>
          {message && <p className={`${status !== 201 ? "text-red-500" : "text-green-500"} pt-4 font-black`}>{message}</p>}
        </Form>
      </Formik>
    </div>
  );
}

export default SubscribeForm;

Enter fullscreen mode Exit fullscreen mode

Awesome! Our newsletter form is up and running like a charm!

So there you have it—Mailchimp is now happily mingling with your Next.js app. If you found this blog post useful, feel free to share the love with others who might need it. And hey, why not hit that follow button for more nerdy goodness on JavaScript, React, and all things web development?

Let's stay in touch on Instagram, Twitter, and GitHub—where the real magic happens.

Thanks for sticking around! 😊

Top comments (1)

Collapse
 
jonathanbc10 profile image
Jonathan B.

Great post. It helped me a lot. I saw a few other, but they were kinda updated.

I just wanted to ask... What if I want to save name and last name as well? :)