Integrating Contact Form 7 with Next.js
Mon Jan 06 2025
Headless WordPress
Next.js
Integrating WordPress with Next.js combines WordPress’s content management power with the flexibility of a modern JavaScript framework. For forms, Contact Form 7 is a popular, free solution known for its simplicity. This tutorial shows how to integrate Contact Form 7 with Next.js to build a headless contact form using the WordPress REST API.
Prefer to use Gravity Forms? Check out Integrating Gravity Forms with Next.js.
Contact Form 7
Install Contact Form 7
To begin, open your WordPress Admin Dashboard, navigate to the Plugins tab in the sidebar, and click Add New Plugin. Search for the Contact Form 7 plugin, install and activate it.
By default, Contact Form 7 doesn’t store submitted messages. If you need to save form submissions in your database, you can install Flamingo, a free WordPress plugin created by the same author as Contact Form 7.
Create a Form
Navigate to the Contact tab in WordPress sidebar, click Add New, and name your form. Then, define the fields you want to include, such as “First Name”, “Last Name”, “Email” and “Message”:
Configure the Mail tab
Adjust the Mail tab settings to match your field names and ensure emails are sent correctly:
By default, Flamingo retrieves values from Contact Form 7’s default input fields:
your-subject
,your-name
, andyour-email
. If your contact form doesn’t include these default fields, the Subject and From fields will not display correctly.To resolve this, you can customize the Flamingo settings in the Additional Settings tab:
Next.js
Install Next.js
To create a project, ensure you have Node.js installed and run the following command:
Give your project a name and select the default options for all prompts. Then, wait for the required dependencies to install.
Install shadcn (Optional)
This tutorial uses shadcn to build the form with pre-designed components. To install, run:
Next, install the components needed for our form: button
, input
, textarea
and label
:
Build a Contact Form
Create a ContactForm
using shadcn components:
Ensure that the field names in this form (e.g.
first-name
) match those in your Contact Form 7 form. This is crucial for mapping the data correctly when sending it to the WordPress REST API.
Next, remove the default Next.js boilerplate code from your homepage and replace it with the ContactForm
component:
Start your Next.js app by running:
Go to http://localhost:3000
in your browser to see your form:
Implement Server Action
To send our form to the WordPress REST API, we will use a Server Action. Before proceeding, retrieve the following details from the Contact Form 7 - Edit Form screen:
- Contact Form ID: This is an integer found in the URL as post=<FORM_ID>
- Unit Tag: This is a 7-character alphanumeric string located in the form’s shortcode
-
The contact form ID will be used directly in our WordPress REST API endpoint:
-
The unit tag will be appended to the body of the form as a value with a key of
_wpcf7_unit_tag
Now we can implement our Server Action. Create a server
directory inside src
and add an actions.ts
file:
Use the server action you created to handle form submissions in the ContactForm
component:
After completing the setup, test the form by submitting it. You should receive a response like this:
You should also receive a notification email and see the form submission in Flamingo - Inbound Messages:
Handling Validation
Handle Error Responses
Sending incorrect data, such as leaving a required field blank or entering an invalid email address, gives us a response like this:
Currently, the user isn’t be notified if something goes wrong. We need to display these errors on the front end to address this.
useActionState
Hook
To handle validation messages, we use the useActionState
React hook. This hook helps manage state transitions for server actions, such as displaying validation errors or showing a success message.
To use it, transform the ContactForm
server component into a client component by adding "use client"
at the top of the file.
We also need to make changes to the server action. Specifically:
-
Add an Extra Parameter: We include the
prevState
parameter because it is required by theuseActionState
hook, but we type it asunknown
since it is not utilized. -
Restructure Validation Messages: Instead of returning an array of invalid field messages, we transform it into an object where:
- The key is the field name
- The value is the corresponding error message
This makes it easier to access validation errors on the front end.
-
Handle General Messages: The response includes a general message, which can be displayed at the bottom of the form. For errors unrelated to WordPress, a generic message—“An unexpected error has occurred. Please try again later.”—is returned.
Here’s the updated server action:
We also utilize the isPending
variable from our hook to disable the submit button while the submission is being processed:
Display Validation Errors
With the updated server action, we can now conditionally render error messages below their respective fields and display the general message at the bottom of the form:
With this changes in place, the form now displays validation messages returned by Contact Form 7:
Preserve User Inputs
When an error occurs, however, all the form fields are cleared, forcing the user to refill the form entirely. This creates a poor user experience. To address this issue, we can send the form data back from the server action to the front end whenever there is an error:
With the original form data available on the front end when an error occurs, we can set it as the default value for each field. If the form is submitted successfully, the payload won’t be sent back to the front end, and the fields will be cleared:
Now, the form preserves the user’s inputs whenever an error occurs:
Conclusion
This tutorial covered how to integrate Contact Form 7 with Next.js to create a headless form submission system. By following these steps, you can leverage WordPress’s content management capabilities while maintaining the flexibility of Next.js.
With this approach, you can:
- Streamline form submissions using the WordPress REST API
- Build dynamic forms with Next.js
- Effectively handle validation and user inputs