Headless Drupal | A simple contact form in Node.js

Open Source Drupal


Node Author

As mentioned earlier: a headless Drupal install has its challenges. Take for example forms: Drupal has a fantastic form api, where Drupal really distincts itself from other cms's. That form api isn't directly available, when you have a decoupled frontend in node.js.

For our decoupled Drupal site we needed a relatively simple contact form. We had to build this custom in Node.js. Here is how we did it:

For the base install, check the headless Drupal & Node.js series.

A simple contact form in Node.js / Express JS

For starters, we have to write the html ourself. Yes, back to basic if you don't have a Drupal form API available :-). In this html you'll also see some server-side Javascript that is supported by Node.js:

This is html form building 101, so I assume there's no explanation needed here. If so, check this.

Furthermore, you'll that at (A) there are dynamically generated status messages with help of server side Javascript. You also see at (C) that filled in data will be remembered. So when the form doesn't validate, visitors don't have to enter their details again. Both are driven by data from the 'main app file', see underneath.

As you can see this form posts to url '/contact' (B). This post must be handled by our Node.js / Express JS install. This is our code in the 'main app file' of our Node.js / Express JS install.

(1) Import the 'nodemailer' npm module

For an explanation about npm modules, check Drupal & Node.js part 2

If a vistor enters data, you want to mail that to a certain email address. We installed the popular nodemailer npm module for this. This module provides functions to send mail via smtp. So install and import that module in your project with help of var nodemailer = require('nodemailer');

app.post

app.post('/contact', function (req, res) {...});

With help of this piece of code you can handle data that's posted to this specific path, '/contact' in for this case.

(2) Honeypot for spam protection

We staged this form to a live environment without this honeypot, huge mistake (of course). Within a few days we were overladed with spam shiznit.

As you can see, this form has 3 elements visible for frontend visitors. But underneath there is a 4th: company name. That element is hidden by css so real human visitor can't see it, spambots do.

So when 'company name' is filled in, we know it's a spambot and stop the whole operation.

(3) Check if all form fields are filled.

The form is html 5 and checks inline if all required fields are filled before a vistor can send it. But there are browsers that by default don't support this. So we have to manually check if all fields are filled. If not: we send the user back to the form with a proper message.

(4) Check for valid email address

To make it easier for ourselfs, we installed an extra npm module: email-validator. If you send a variable through a function of this module, you can check if the email is valid. If not: send the user back to the form with a proper message.

(5) & (6) Send email via SMTP in node.js / Express JS

With help of the imported npm module 'nodemailer', we can now send the filled in form-data from the visitor. The nodemailer module has predefined templates for services like Gmail. If we use that we can relatively easy send emails via Gmail (6).

(7) Provide error message when not sent

The nodemailer als comes with error handling. When an email didn't get send, it provides errors so you can provide feedback to the user that was trying to send a message via your contact form.

Wrap up

Alrighty, this was an intro about forms for when you have a decoupled Drupal site with Node.js / Express JS at the frontend. But it can become more complex when you have to send and validate data to and through Drupal. We already did that in other headless drupal installs and I will write about that in a next headless blog. So stay tuned yo!

-- Cheers, Joris