Webflow form processing using nodemailer & Firebase cloud functions

Robin Granqvist
Geek Culture
Published in
8 min readJun 4, 2021
Cover photo

Webflow is amazing. It really is.

And building your own forms are no exception. They have made it super easy to design, build and use any kind of forms throughout your sites.

So, if it’s so easy, why bother reading this guide and create your own third party form processor?

Well, there are a few cases in which Webflow aren’t the optimal solution.

The single most common problem occurs when wanting to export your code and host it on other platform than on Webflow itself.

By exporting your code, you get access to all of your static front-end code, but all the fancy, complicated & nerdy back-end stuff is gone. This includes any possibility of any form usage.

To battle this problem, Webflow users commonly use other no-code tools in order to process the form data. Some of the ones you’ll find recommended are:

Now, I haven’t tried any of these, but I’m sure they‘re all great. I just feel like the pricing is fairly steep for such a basic tool.

And that’s why you should continue reading.

This guide will show you how to program your own form data processor that will stay free of charge in 99,9% of use cases (unless you’re handling tens of thousands of form requests on a monthly basis).

So let’s get started.

Setup

In order to follow along, you would need the following:

  • A code editor. I love my little VSCode.
  • A Webflow account
  • A Firebase account
  • Node.js installed on your computer
  • An outlook / hotmail or Gmail account. (I’ll be using a hotmail account in this guide)

Let’s get going by creating a new Firebase project.

A new Firebase project

I call my project “webflow-node-mail”. Setting up a new Firebase project is incredibly simple.

You can use this guide by codinglatte in case you get stuck.

Firebase project intro page

We want to make use of Firebase’s feature called “cloud functions”.

These are basically Javascript (Node) functions that runs in the cloud, and are envoked on demand whenever a request hits its endpoint.

This may sound complicated and intimidating, but trust me, you’ll understand more in a bit.

In order to make use of cloud functions in a Firebase project, you unfortonately have to upgrade the project to a “Blaze plan”,

This is done by connecting a credit / debit card to your account, and selecting the “Blaze plan” option.

Firebase pricing plans

Don’t worry though, unless your handling tens of thousands of form requests per month, you’ll probably not pay one cent.

You can read more about the Firebase pricing plans by clicking here. (Up to 2 million function invocations per month for free etc.).

The Firebase CLI

Okay, let’s setup the Firebase CLI in order to be able to create Firebase projects locally on your computer.

Open a terminal (inside VSCode for example) and install it directly from NPM by using the following commando:

npm install -g firebase-tools

This will install the CLI globally on your computer, enabling you to create new Firebase projects anywhere throughout your machine. Amazing.

Now login to Firebase by using the following commando:

firebase login

A browser will popup, and you’ll be able to login with your Google account. Cool.

A Firebase cloud function

Now create a folder for your code and navigate to it through your terminal. We’re only initializing for usage of functions, since we don’t need any other Firebase features for this project.

firebase init functions

Select “use an existing project” in order to sync your Firebase project with your local machine.

You’ll probably see a few options popping up in the terminal. For example, you’re able to choose between using Javascript or Typescript, using Eslint for linting etc. Choose whatever you’re comfortable with.

When finished, you should see a few files and folders being created in your local project folder.

It should look something like this:

Firebase functions folder and file structure

The index.js file highlighted in the image is the file that you’ll work with for the rest of this project. Open it up in your text editor.

Firebase gives you some boilerplate code looking something like this:

Firebase cloud function starting code

The majority of the code will be written inside this “export”, and will be envoked whenever a request hits its endpoint.

So let’s start coding.

Nodemailer

Nodemailer is a package for Node.js that lets you send emails through your own email account(s). It’s fairly simple to work with, and seems to work very well for things like these.

Install nodemailer in your “functions” folder by using the following command in your terminal:

npm install nodemailer

The cloud function

In order for Nodemailer to send an email, we need to do the following:

  • Create a “transporter” object containing our email authentication
  • Accept data from our Webflow form
  • Temporarily store our data
  • Send the data through our transporter into our mail

Start by importing the nodemailer package in our index.js file by using the following code:

const nodemailer = require("nodemailer");

Now create the transporter. It should contain the following attributes:

  • The service you want to use (in my case hotmail)
  • Your username and password
  • Some kind of node.js TLSSocket option (tbh I’m not totally read about what this one is for, but if it works it works).

So let’s create a new object looking something like the following:

const transporter = nodemailer.createTransport({  service: "hotmail",  auth: {    user: "youremail@hotmail.se",    pass: "yourpassword",  },  tls: {    rejectUnauthorized: false,  },});

Now let’s continue with our options object. As mentioned earlier, we want to populate this with the data sent through our form.

const subject = req.body.subject;
const name = req.body.name;
const message = req.body.message;
const options = { from: "youremail@hotmail.se", to: "youremail@hotmail.se", subject: subject, html: `<b>Message sent from ${name}</b><br><br>${message}`,};

As you can see, I’m using the request (short: req) variable in order to get access to whatever data is sent to the endpoint.

The name of these are based on what you name your form inputs in Webflow, so make sure you remember them. Mine are the following:

  • Name (req.body.name)
  • Subject (req.body.subject)
  • Message (req.body.message)

Depending on the size of your form, you can have as many or as few of these data attributes as you want.

In your “options object” you should specify from which account the email address is sent, as well as which address it should be sent to.

You’re required to use the email you authenticated above as your “from” email, but the data can be sent to one or more different addresses.

If you want to send it to more than one, you can create an array of addresses like so:

to: ["youremail@hotmail.se", "anotheremail@hotmail.com"]

You’re also able to style your email by using HTML like I do using the “html” attribute in the options object.

I’m simply using a bold text style for the name, and a couple break lines for the message.

html: `<b>Message sent from ${name}</b><br><br>${message}`

Okay, now we have access to the data in our function. Let’s send it further to our email address.

We need to use a method called “sendMail” in our transporter object. We’re able to specify what we want to happen on success as well as on errors.

I’ve created two pages in my Webflow project called “success” and “error” (similarly to what you would do by using the native forms) and simply redirect the user to one of these based on success or errors.

transporter.sendMail(options, function(err) {  // Error  if (err) {    return res.redirect("https://node-mailer-  form.webflow.io/error");  }  // Success  return res.redirect("https://node-mailer-form.webflow.io/success");});

And that’s all for our function. Check out, copy and / or modify the full code below.

CODE

Now we need to deploy the function. We do this by using the following command in our terminal:

firebase deploy

Simple like that. Amazing.

The deployment may take a little while, but it should be finished in a minute or two. You should see something like this when finished:

Terminal when deploying a cloud function to Firebase

Now let’s go over to Webflow and create our form.

Here’s the full code for my function:

The Webflow form

My form is super simple, but works well for this example.

A simple form in Webflow

Now it’s extremely important that you name your inputs correctly. As mentioned earlier, the names of the inputs are used in our nodemailer function.

Here’s an example of the settings for my email input:

webflow input settings

The name attribute for all input fields should correlate with the names used in our cloud function.

Now we need to specify an action endpoint for our form. Go to your Firebase console, enter your project and navigate to “functions”.

Here you should find your deployed function.

Simply copy and paste the URL for your function and paste it as your “action URL” in the form settings in Webflow.

The Firebase console fuctions page
Webflow form settings

The last part is changing your form method from GET to POST. Amazing.

Now we can test out our form. Publish your Webflow site and send a submission.

If everything works correctly, you should be redirected to whatever url you specified in your function, and your inbox should look something like this:

An email sent successfully

And that’s all ladies and gentlemen.

You have now created your own, modifiable, free and very beautiful little cloud function that’s able to process any form data for you.

If you have any questions, feel free to leave a comment and I’ll try to reply.

Have fun,

Robin 🤙

--

--

Robin Granqvist
Geek Culture

design // web development // music production // minimalism