How To Add Notion To Your Email Capture Page

Bilal Tahir
4 min readJun 19, 2021
email captured on notion

This is part 2 of my guide on How To Create A Stylish Email Capture Page In Tailwind CSS. In this post, we will add functionality to our beautiful form and hook it up with Notion so emails get recorded in a database there.

You can find the code for this tutorial here.

Add State

Step 1 is to add some state. Once someone has subscribed we want to show a message that they have, actually, subscribed. This can be extended with a follow up email notification but that is beyond the scope of this article.

To achieve this we will add the following state to our HeroContent component.

const [subscribed, setSubscribed] = useState(false)

And set this to true when we capture the email in state. We can pass setSubscribed as a prop to our Subscribe component and trigger this when the form is submitted in our handleSubmit function.

Set State

async function handleSubmit(e) {
e.preventDefault()
setSubscribed(true)
}

Note we also want to keep track of the email in the form so we will add another variable for that called email

const [email, setEmail] = useState(‘’)

and update this in the onChange function in our input.

onChange={(e) => setEmail(e.target.value)}

Now we can use this conditional to show a different message when it is true.

Show Success Message

<h1 className='text-center text-3xl sm:text-4xl font-extrabold sm:leading-[3rem]'>
Your headline here.{' '}
<span className='text-yellow-400'>Catch their attention!</span>
</h1>

Let’s see how this looks.

subscribe flow

Nice! Now all that is left is to hook up Notion. Let’s add to our handleSubmit function in our Subscribe component.

Add Submit Function

async function handleSubmit(e) {
e.preventDefault()
await fetch(‘api/update-notion’, {
method: ‘POST’,
headers: {
‘Content-type’: ‘application/json’,
},
body: JSON.stringify({ email }),
})
setSubscribed(true)
}

We are calling a serverless function to access Notion. We are simply passing the email in our POST request here. Now — let’s create this update-notion function.

Setup Notion API & Database

But wait — before we do that we need to make sure we have an API and Database setup in Notion to receive our email!

This guide walks through the setup in more detail. The tldr is that you need a Notion API key to access Notion (duh) and then a database Id so we know which table in Notion to update. The database Id can be easily found in the url of the table.

https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...                            | — — — — — Database ID — — — — |

For our example make sure you have a table setup with an Email header similar to the table shown in the main image.

Once we have this setup we can add our Ids to our .env.local file.

MY_NOTION_TOKEN=
DATABASE_ID=

Create Serverless Function

Finally time to create our function!

export default async function (req, res) {
try {
await fetch(‘https://api.notion.com/v1/pages', {
method: ‘POST’,
headers: {
‘Content-type’: ‘application/json’,
Authorization: `Bearer ${process.env.MY_NOTION_TOKEN}`,
‘Notion-Version’: ‘2021–05–13’,
},
body: JSON.stringify({
parent: { database_id: `${process.env.DATABASE_ID}` },
properties: {
Email: {
title: [
{
text: {
content: `${req.body.email}`,
},
},
],
},
},
}),
})
} catch (err) {
console.log(‘Error’, err)
}
res.status(200).json({ status: ‘success’ })
}

Let’s break this down. We are doing a POST request using our NOTION token for Authorization in the header. We also pass along the DATABASE_ID in the parent component and finally the email in the property key of the body.

If you had another field we would add it to properties similar to the structure we have for Email (with a title, text, content format).

The astute among you might have noticed that we calling a function to call a function so why not just call this directly? The reason is we will run into CORS issues if we try to call Notion directly form our handleSubmit function and so we have to do it via a serverless function.

And that’s it! We now have a full workflow going.

final demo

Pretty slick! And you can easily extend this with more fields, functionality. Of course Notion is only one option. We can also do this with other databases like Airtable or even Google Sheets!

You can find the code for this tutorial here.

Let me know how you are using this cool workflow. :)

Cheers,
Bilal

--

--