How to integrate MailChimp in a JavaScript web app

By Timur (Tima) Zhiyentayev
If you are a blogger, publisher, or business owner who does content marketing, having a newsletter is a must. In this tutorial, you will learn how to add Mailchimp integration to a simple JavaScript app. You’ll ultimately build a form for guest users to subscribe to a newsletter.
I wrote this tutorial for a junior/mid-career web developer. The tutorialassumes some basic knowledge of React, JavaScript, and HTTP.
You’ll start the tutorial with a boilerplate app, gradually add code to it, and finally test Mailchimp API integration.
The boilerplate app is built with React, Material-UI, Next, Express, Mongoose, and MongoDB. Here’s more about theboilerplate.
As mentioned above, our goal is to create a feature that allows a guest user to subscribe to a MailChimp newsletter. The user subscribes by manually adding their email address to a form on your website. Here is an overview of the data exchange that will occur between the client (browser) and server:
- A user adds their email address to the form and clicks
submit
- The click triggers a client-side API method that sends the email address from the user’s browser to your app server
- The client-side API method sends a POST request to a unique Express route
- The Express route passes the email address to a server-side API method that sends a POST request to Mailchimp’s server
- The email address is successfully added to your Mailchimp list
Specifically, you will achieve the following by the end of this tutorial:
- Create a
Subscribe
page with a subscription form - Define an API method called
subscribeToNewsletter()
using thefetch()
method - Define an Express route
'/subscribe'
- Define a
subscribe()
API method that sends a POST request to Mailchimp's API server - Test out this data exchange with Postman and as a guest user
Getting started
For this tutorial, we’ll use code located in the1-start folder of ourbuilderbook repo. If you don’t have time to run the app locally, I deployed this example app at:https://mailchimp.builderbook.org/subscribe
To run the app locally:
- Clone the builderbook repo to your local machine with:
git clone git@github.com:builderbook/builderbook.git
- Inside the
1-start
folder, runyarn
ornpm install
to install all packages listed inpackage.json
.
To add Mailchimp API to our app, we will install and learn about the following packages:
Let’s start by putting together theSubscribe
page. In addition to learning about the Mailchimp API, you will get familiar withNext.js, a framework for React apps.
A key feature of Next.js is server-side rendering for initial page load. Other features include routing, prefetching, hot code reload, code splitting, and preconfigured webpack.
Subscribe page
We will define aSubscribe
component as a child ofES6 class usingextends.
Instead of:
const Subscribe = React.createClass({})
We will use:
classSubscribeextendsReact.Component{}
We will not specifyReactDOM.render()
orReactDOM.hydrate
explicitly, since Next.js implements bothinternally.
A high-level structure for ourSubscribe
page component is:
import Reactfrom'react';// other imports
classSubscribeextendsReact.Component{ onSubmit =(e) => {// check if email is missing, return undefined // if email exists, call subscribeToNewsletter() API method };
render() {return (// form with input and button ); }}
exportdefault Subscribe;
Create asubscribe.js
file inside thepages
folder of1-start
. Add the above code to this file. We will fill the// other imports
section as we go.
Our form will have only two elements: (1) an input element for email addresses and (2) a button. Since our boilerplate app is integrated with Material-UI, we’ll useTextField andButton components from the Material-UI library. Add these two imports to yoursubscribe.js
file:
import TextFieldfrom'material-ui/TextField';import Buttonfrom'material-ui/Button';
Put theTextField
andButton
components inside a<fo
rm> element:
<form onSubmit={this.onSubmit}><p>We will email you when a new tutorial is released:</p><TextFieldtype="email"label="Your email"style={styleTextField}required /><p /><Buttonvariant="raised"color="primary"type="submit">Subscribe </Button></form>
You can see that we passed some props to bothTextField
andButton
components. For a complete list of props you can pass, check out the official docs forTextField props andButton props.
We need to get an email address specified inTextField
. To access the value ofTextField
, we add React'sref attribute to it:
inputRef={(elm) => {this.emailInput = elm;}}
We access the value with:
this.emailInput.value
Two notes:
- We did not use
ref="emailInput"
, since React documentation recommends using the contextual objectthis
. In JavaScript,this
is used to access an object in the context. If you configure Eslint properly, you would see an Eslint warning for thisrule. - Instead of
ref
, we usedinputRef
since theTextField
component is not aninput
HTML element.TextField
is a component of Material-UI and uses theinputRef
prop instead ofref
.
Before we define ouronSubmit
function, let's run our app and take a look at our form. Your code at this point should look like:pages/subscribe.js
import Reactfrom'react';import Headfrom'next/head';import TextFieldfrom'material-ui/TextField';import Buttonfrom'material-ui/Button';
import { styleTextField }from'../components/SharedStyles';import withLayoutfrom'../lib/withLayout';
classSubscribeextendsReact.Component{ onSubmit =(e) => {// some code };
render() {return (<divstyle={{padding: '10px45px' }}><Head><title>Subscribe</title><metaname="description"content="description for indexing bots" /></Head><br /><formonSubmit={this.onSubmit}><p>We will email you when a new tutorial is released:</p><TextFieldinputRef={(elm) => { this.emailInput = elm; }} type="email" label="Your email" style={styleTextField} required /><p /><Buttonvariant="raised"color="primary"type="submit"> Subscribe</Button></form></div> ); }}
exportdefault withLayout(Subscribe);
A few notes:
- In Next.js, you can specify page title and description using
Head
. See how we used it above. - We added a
styleTextField
style. We keep this style incomponents/SharedStyles.js
, so that it's reusable and can be imported into any component or page. - We wrapped the
Subscribe
component withwithLayout
. The higher-order componentwithLayout
ensures that a page gets aHeader
component and is server-side rendered on initial load.
We access theSubscribe
page at the/subscribe
route, since Next.js creates the route for a page from the page's file name inside thepages
folder.
Start your app withyarn dev
and go to[http://localhost:8000/subscribe](http://localhost:8000/subscribe:)
The form looks as expected. Try changing the values passed to different props of theTextField
andButton
components. For example, change text for thelabel
prop toType your email
and change the Buttonvariant
prop toflat
:
Before we continue, click theLog in
link in theHeader
. Note the loading progress bar at the top of the page. We implemented this bar withNprogress, and we will show it while waiting for our code to send an email address to a Mailchimp list.
Our next step is to define theonSubmit
function. The purpose of this function is to get the email address fromTextField
, pass that email address to an API methodsubscribeToNewsletter
, and then call the method.
Before we callsubscribeToNewsletter(email)
, let's prevent a default behavior of our<fo
rm> element and define
email:
- Prevent the default behavior ofsending form data to a server with:
e.preventDefault();
- Let’s define a local variable
email
. It has the valuethis.emailInput.value
if boththis.emailInput
andthis.emailInput.value
exist, otherwise it is null:
const email = (this.emailInput &&this.emailInput.value) ||null;
- If
email
is null, the function should return undefined:
if (this.emailInput && !email) {return;}
So far we have:
onSubmit =(e) => { e.preventDefault();
const email = (this.emailInput &&this.emailInput.value) ||null;
if (this.emailInput && !email) {return; }
// call subscribeToNewsletter(email)};
To call our API methodsubscribeToNewsletter(email)
, let's use theasync/await
construct together withtry/catch
. We cover async callbacks,Promise.then
, andasync/await
in detail inour book.
To useasync/await
, prependasync
to an anonymous arrow function like this:
onSubmit =async (e) =>
ProvidingsubscribeToNewsletter(email)
should return a Promise (and it does — we define this method later in this tutorial using JavaScript'sfetch()
method that returns a Promise). You can prependawait
tosubscribeToNewsletter(email)
:
await subscribeToNewsletter({ email })
You get:
onSubmit =async (e) => { e.preventDefault();
const email = (this.emailInput &&this.emailInput.value) ||null;
if (this.emailInput && !email) {return; }
try {await subscribeToNewsletter({ email });
if (this.emailInput) {this.emailInput.value =''; } }catch (err) {console.log(err);//eslint-disable-line }};
JavaScript will pause at the line withawait subscribeToNewsletter({ email });
and continue only aftersubscribeToNewsletter({ email })
returns a response with a success or error message.
In the case of success, let’s clear our form with:
if (this.emailInput) {this.emailInput.value =''; }
Before we define oursubscribeToNewsletter
API method, let's make a UX improvement. UseNProgress.start();
to start bar loading and useNProgress.done();
to complete bar loading:
onSubmit =async (e) => { e.preventDefault();
const email = (this.emailInput &&this.emailInput.value) ||null;
if (this.emailInput && !email) {return; }
NProgress.start();
try {await subscribeToNewsletter({ email });
if (this.emailInput) {this.emailInput.value =''; }
NProgress.done(); }catch (err) {console.log(err);//eslint-disable-line NProgress.done(); }};
With this change, a user who submits a form will see the progress bar.
Code for yourSubscribe
page should look like:pages/subscribe.js
import Reactfrom'react';import Headfrom'next/head';import TextFieldfrom'material-ui/TextField';import Buttonfrom'material-ui/Button';import NProgressfrom'nprogress';
import { styleTextField }from'../components/SharedStyles';import withLayoutfrom'../lib/withLayout';import { subscribeToNewsletter }from'../lib/api/public';
classSubscribeextendsReact.Component{ onSubmit =async (e) => { e.preventDefault();
const email = (this.emailInput &&this.emailInput.value) ||null;
if (this.emailInput && !email) {return; }
NProgress.start();
try {await subscribeToNewsletter({ email });
if (this.emailInput) {this.emailInput.value =''; }
NProgress.done();console.log('non-error response is received'); }catch (err) {console.log(err);//eslint-disable-line NProgress.done(); } };
render() {return (<divstyle={{padding: '10px45px' }}><Head><title>Subscribe</title><metaname="description"content="description for indexing bots" /></Head><br /><formonSubmit={this.onSubmit}><p>We will email you when a new tutorial is released:</p><TextFieldinputRef={(elm) => { this.emailInput = elm; }} type="email" label="Your email" style={styleTextField} required /><p /><Buttonvariant="raised"color="primary"type="submit"> Subscribe</Button></form></div> ); }}
exportdefault withLayout(Subscribe);
Start your app withyarn dev
and make sure your page and form look as expected. Submitting a form won't work yet, since we haven't defined the API methodsubscribeToNewsletter()
.
subscribeToNewsletter API method
As you may have noticed from the import section ofpages/subscribe.js
, we will definesubscribeToNewsletter()
atlib/api/public.js
. We placedsubscribeToNewsletter()
to thelib
folder to make ituniversally accessible, meaning this API method will be available on both client (browser) and server. We do so because in Next.js, page code is server-side rendered on initial load and client-side rendered on subsequent loads.
In our case, when a userclicks a button on the browser to callsubscribeToNewsletter()
, this method will run only on the client. But imagine that you have agetPostList
API method that fetches a list of blog posts. To render a page with a list of postson the server, you have to makegetPostList
universally available.
Back to our API methodsubscribeToNewsletter()
. As we discussed in the introduction to this tutorial, our goal is to hook up a data exchange between client and server. In other words, our goal is to build an internal API for our app. That's why we callsubscribeToNewsletter()
an API method.
The purpose ofsubscribeToNewsletter()
is tosend a request to the server at a particular route called an API endpoint and then receive a response. We discuss HTTP and request/response in detailhere.
To understand this tutorial, you should know that a request that passes data to the server and does not require any data back is sent with thePOST
method. Usually, the request'sbody
contains data (in our case, email address).
In addition to sending a request, oursubscribeToNewsletter()
method should wait for a response. The response does not have to contain any data — it could be a simple object with one parameter{ subscribed: 1 }
or{ done: 1 }
or{ success: 1 }
.
To achieve both sending a request and receiving a response, we use thefetch()
method. In JavaScript,fetch() is a global method that is used for fetching data over a network by sending a request and receiving a response.
We use theisomorphic-fetch
package that makesfetch()
available in our Node environment. Install this package with:
yarn add isomorphic-fetch
Here’s an example of usage from thepackage’s README:
fetch('//offline-news-api.herokuapp.com/stories') .then(function(response){if (response.status >=400) {thrownewError("Bad response from server"); }return response.json(); }) .then(function(stories){console.log(stories); });
Let’s use this example to write a reusablesendRequest
method that takespath
and some otheroptions
, passes a request object (object that hasmethod
,credentials
andoptions
properties), and calls thefetch()
method.fetch()
takespath
and the request object as arguments:
asyncfunctionsendRequest(path, options = {}){const headers = {'Content-type':'application/json; charset=UTF-8', };
const response =await fetch(`${ROOT_URL}${path}`,Object.assign({method:'POST',credentials:'include' }, { headers }, options), );
const data =await response.json();
if (data.error) {thrownewError(data.error); }
return data;}
Unlike the example fromisomorphic-fetch
, we used our favoriteasync/await
construct instead ofPromise.then
(for better code readability).
Object.assign() is a method thatcreates a new object out of three smaller objects:{ method: 'POST', credentials: 'include' }
,{ headers }
, andoptions
. The objectoptions
is empty by default, but it could be, for example, the request'sbody
property. Since we need to pass an email address, our case indeed uses thebody
property.
As you may have noticed from the code, we need to defineROOT_URL
. We can write conditional logic forROOT_URL
that takes into considerationNODE_ENV
andPORT
, but for simplicity’s sake, we define it as:
const ROOT_URL ='http://localhost:8000';
It’s time to define oursubscribeToNewsletter
method with the help of thesendRequest
method:
exportconst subscribeToNewsletter =({ email }) => sendRequest('/api/v1/public/subscribe', {body:JSON.stringify({ email }), });
As you can see, we pass{ body: JSON.stringify({ email }), }
as anoptions
object to add an email address to the body of the request object.
Also we chose/api/v1/public/subscribe
as ourpath
, that is the API endpoint for our internal API that adds a user email address to our Mailchimp list.
Put it all together and the content of thelib/api/public.js
should be:lib/api/public.js
import'isomorphic-fetch';
const ROOT_URL ='http://localhost:8000';
asyncfunctionsendRequest(path, options = {}){const headers = {'Content-type':'application/json; charset=UTF-8', };
const response =await fetch(`${ROOT_URL}${path}`,Object.assign({method:'POST',credentials:'include' }, { headers }, options), );
const data =await response.json();
if (data.error) {thrownewError(data.error); }
return data;}
exportconst subscribeToNewsletter =({ email }) => sendRequest('/api/v1/public/subscribe', {body:JSON.stringify({ email }), });
Good job reaching this point! We defined oursubscribeToNewsletter
API method that sends a request to the API endpoint/api/v1/public/subscribe
and receives a response.
Start your app withyarn dev
, add an email address, and submit the form. In your browser console (Developer tools > Cons
ole), you will see an expected POST
404 error:
That error means that the request was successfully sent to the server, but the server did not find what was requested. This is expected behavior since wedid not write any server code that sends a response to the client when a request is sent to corresponding API endpoint. In other words, we did not create the Express route/api/v1/public/subscribe
that handles the POST request we sent using thesubscribeToNewsletter
API method.
Express route/subscribe
An Express route specifies a function that gets executed when an API method sends a request from the client to the route’s API endpoint. In our case, when our API method sends a request to the API endpoint/api/v1/public/subscribe
, we want the server to handle this request with an Express route that executes some function.
You can use the classexpress.Router()
and syntaxrouter.METHOD()
to modularize Express routes into small groups based on user type:
const router = express.Router();router.METHOD('API endpoint', ...);
If you’d like to learn more, check out the official Express docs onexpress.Router() androuter.METHOD().
However, in this tutorial, instead of modularizing, we will use:
server.METHOD('API endpoint', ...);
And place the above code directly into our main server code atserver/app.js
.
You already have enough information to put together a basic Express route:
- The method is POST
- The API endpoint is
/api/v1/public/subscribe
- From writing
onSubmit
andsubscribeToNewsletter
, you know about an anonymous arrow function - From writing
onSubmit
, you know about thetry/catch
construct
Put all this knowledge together, and you get:
server.post('/api/v1/public/subscribe',(req, res) => {try { res.json({subscribed:1 });console.log('non-error response is sent'); }catch (err) { res.json({error: err.message || err.toString() }); }});
A couple of notes:
- We wrote
error: err.message || err.toString()
to handle both situations: when the error is a type of string and when the error is an object. - To test out our Express route, we added the line:
console.log(‘non-error response is sent’);
Add the above Express route toserver/app.js
after this line:
const server = express();
It’s time to test!
We recommend using thePostman app for testing out a request-response cycle.
Look at this snapshot of request properties in Postman:
You need to specify at least three properties (similar to when we wrote thesubscribeToNewsletter
API method):
- Select POST method
- Specify the full path for the API endpoint:
[http://localhost:8000/api/v1/public/subscribe](http://localhost:8000/api/v1/public/subscribe)
- Add a
Content-Type
header with the valueapplication/json
Make sure your app is running. Start it withyarn dev
. Now click theSend
button on Postman.
If successful, you will see the following two outputs:
- On Postman, you see the response has code 200 and the following body:
- Your terminal prints:
Good job, you just wrote a working Express route!
At this point, you showed that two events happen successfully in your app: a request gets sent and a response is received. However, wedid not pass an email address to a function inside our Express route. To do so, we need to accessreq.body.email
, because this is where we saved the email address when defining thesubscribeToNewsletter
API method:
const email = req.body.email;
With ES6 object destructuring, it becomes shorter:
const { email } = req.body;
If theemail
local variable does not exist, then let's send a response with an error and return undefined (exit with blankreturn
):
if (!email) { res.json({error:'Email is required' });return;}
Also, modify theconsole.log
statement to print outemail
.
After these modifications, you get:
server.post('/api/v1/public/subscribe',async (req, res) => {const { email } = req.body;
if (!email) { res.json({error:'Email is required' });return; }
try { res.json({subscribed:1 });console.log(email); }catch (err) { res.json({error: err.message || err.toString() }); }});
Let’s test it out. Open Postman, and add one more property to our request:body
with valueteam@builderbook.org
. Make sure that you selected theraw > J
SON data format:
Make sure that your app is running and then click theSend
button.
Look at the response on Postman and the output of your terminal:
- Postman will display
Loading...
but never finish - Terminal outputs an error:
TypeError: Cannot read property 'email' of undefined
Apparently, theemail
variable is undefined. To read theemail
property fromreq.body
, you need a utility that decodes thebody
object of a request from Unicode to JSON format. This utility is calledbodyParser
,read more about it here.
InstallbodyParser
:
yarn add body-parser
Import it toserver/app.js
with:
import bodyParserfrom'body-parser';
Mount JSONbodyParser
on the server. Add the following line right afterconst server = express();
andbefore your Express route:
server.use(bodyParser.json());
An alternative to using the externalbodyParser
package is to use internal Express middlewareexpress.json(). To do so, remove the import code forbodyParser
and replace the above line of code with:
server.use(express.json());
We are ready to test. Make sure your app is running and click theSend
button on Postman.
Take a look at the response on Postman and your terminal:
- Postman successfully outputs:
"subscribed": 1
- Terminal has no error this time, instead it prints:
team@builderbook.org
Great, now the request’sbody
is decoded and available inside the Express route's function asreq.body
.
You successfully added the first internal API to this app! Data exchange between client and server works as expected.
Inside the Express route that we wrote earlier, we want to call and wait for asubscribe
method that sends a POST request from our server to Mailchimp's. In the next and final section of this tutorial, we will discuss and write thesubscribe
method.
Method subscribe()
We wrote code for proper data exchange between our server and a user’s browser. However, to add a user’s email address to a Mailchimp list, we need to send aserver to server POST request. POST request fromour server toMailchimp’s server.
To send a server to server request, we will use therequest
package. Install it:
yarn add request
As with any request, we need to figure out which API endpoint and what request properties to include (headers
,body
and so on):
- Create a
server/mailchimp.js
file. - Import
request
. - Define
request.post()
(POST request) with these properties:uri
,headers
,json
,body
, and callback.
server/mailchimp.js
:
import requestfrom'request';
exportasyncfunctionsubscribe({ email }){const data = {email_address: email,status:'subscribed', };
awaitnewPromise((resolve, reject) => { request.post( {uri:// to be discussed headers: { Accept: 'application/json', Authorization: // to be discussed, }, json: true, body: data, }, (err, response, body) => { if (err) { reject(err); } else { resolve(body); } }, ); });}
All properties are self-explanatory, but we should discussuri
(or API endpoint) andAuthorization
header:
uri
. Earlier in this chapter, we pickedhttp://localhost:8000/api/v1/public/subscribe
as our API endpoint. We could've picked any route for our internal API. However, Mailchimp’s API is external. Thus we should check the official documentation to find the API endpoint that adds an email address to a list. Read more about theAPI to add members to a list. The API endpoint is:
https://usX.api.mailchimp.com/3.0/lists/{LIST_ID}/members
RegionusX
is a subdomain. Follow these steps to find the subdomain for an API endpoint:
- sign up or log in to Mailchimp
- go to
Account > Extras > API keys > Your
API keys - your API key may look like
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us17
That means the region isus17
and your app will send requests to the Mailchimp subdomain:
https://us17.api.mailchimp.com/3.0/lists/{LIST_ID}/members
VariableLIST_ID
is the List ID of a particular list in your Mailchimp account. To findList ID
, follow these steps:
- On your Mailchimp dashboard, go to
Lists > click the list name > Settings > List name and
defaults - Find the section
List ID
Get the
xxxxxxxxxx
value from this section, it's yourLIST_ID
Authorization
header. We need to send ourAPI_KEY
insideAuthorization
header to Mailchimp's server. This tells Mailchimp's server that our app is authorized to send a request. Read more aboutAuthorization header here (headers.Authorization
). Syntax forAuthorization
header:
Authorization:
- In our case:
Authorization: Basic apikey:API_KEY
TheAPI_KEY
must be base64 encoded. Follow thisexample.
After encoding:
Authorization:`Basic${Buffer.from(`apikey:${API_KEY}`).toString(‘base64’)}`
To findAPI_KEY
:
- On your Mailchimp dashboard, go to
Account > Extras > API keys > Your
API keys - Your API key may look like
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us17
Where are we going to storelistId
andAPI_KEY
values? You can store all environmental variable in a.env
file and manage them with thedotenv package. However, to stay focused in this tutorial, we add values directly to ourserver/mailchimp.js
file:
const listId ='xxxxxxxxxx';const API_KEY ='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us17';
Plug in the above code snippets:
import requestfrom'request';
exportasyncfunctionsubscribe({ email }){const data = {email_address: email,status:'subscribed', };
const listId ='xxxxxxxxxx';const API_KEY ='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us17';
awaitnewPromise((resolve, reject) => { request.post( {uri:`https://us17.api.mailchimp.com/3.0/lists/${listId}/members/`,headers: {Accept:'application/json',Authorization:`Basic${Buffer.from(`apikey:${API_KEY}`).toString('base64')}`, },json:true,body: data, },(err, response, body) => {if (err) { reject(err); }else { resolve(body); } }, ); });}
Remember to add real values forlistId
andAPI_KEY
.
Testing
It’s time to test out the entire MailChimp subscription flow.
We exported oursubscribe
method fromserver/mailchimp.js
, but we haven't imported/added this method to the Express route atserver/app.js
. To do so:
- Import to
server/app.js
with:
import { subscribe }from ‘./mailchimp’;
- Add an
async/await
construct to the Express route, so we calland wait for thesubscribe
method. Modify the following snippet of code like this:
server.post('/api/v1/public/subscribe',async (req, res) => {const { email } = req.body;if (!email) { res.json({error:'Email is required' });return; }
try {await subscribe({ email }); res.json({subscribed:1 });console.log(email); }catch (err) { res.json({error: err.message || err.toString() }); }});
We were able to useawait
forsubscribe
because this method returns a Promise. Recall the definition ofsubscribe
— it has a line withnew Promise()
.
Let’s add aconsole.log
statement to theonSubmit
function frompages/subscribe.js
. Open yourpages/subscribe.js
file and addconsole.log
like this:
try {await subscribeToNewsletter({ email });
if (this.emailInput) {this.emailInput.value =''; } NProgress.done();console.log('email was successfully added to Mailchimp list');}catch (err) {console.log(err);//eslint-disable-line NProgress.done();}
At this point, we can skip testing with Postman. Instead, let’s start our app, fill out the form, submit the form, and check if the email was added to the Mailchimp list. Also, we will see the output of our browser console.
Start your app withyarn dev
. Go tohttp://localhost:8000/subscribe
. Take a look at the empty list on your Mailchimp dashboard:
Fill out the form and clickSubscribe
. Refresh the page with the Mailchimp list:
And the browser console prints:
In case you are not running the app locally, you can test on the app I deployed for this tutorial:https://mailchimp.builderbook.org/subscribe. You’ll get a test email to confirm that MailChimp API worked.
Boom! You just learned two powerful skills: building internal and external APIs for your JavaScript web application.
When you complete this tutorial, your code should match code in the1-end folder. This folder is located in thetutorials
directory of ourbuilderbook repo.
If you found this article useful, consider giving a star to ourGithub repo and checking out ourbook where we cover this and many other topics in detail.
If you are building a software product, check out ourSaaS boilerplate andAsync (team communication philosophy and tool for small teams of software engineers).
If you read this far, thank the author to show them you care.
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers.Get started