How To Build a WordPress Contact Form


One feature common to almost every website in the world is the contact form. It can be used to collect feedback, complaints or useful information from website clients and users.

A typical contact form consists of the following fields – sender name, sender email address, email subject and the message.

Create Contact Form WordPress

In this tutorial, you will learn to build a simple contact form with a WordPress plugin.

Contact Form PHP Class Synopsis

The contact form PHP class will consist of a property and six methods (known as “functions” in procedural programming).

class Designmodo_contact_form {
private $form_errors = array();

function __construct() {
// ...

static public function form() {
// ...

public function validate_form() {
// ...

public function send_email() {
// ...

public function process_functions() {
// ...

public function shortcode() {
// ...


The private property $form_errors is an array that will store all the errors that will be generated by the contact form. I will explain what each class method does as we walk through the coding of the contact form plugin.

Coding the Contact Form Plugin

Like other WordPress plugins, the header is first thing to go into the plugin file. Below is our contact form header followed by the class declaration and property.


  Plugin Name: Designmodo Contact Form
  Plugin URI:
  Description: Simple Contact form plugin that just work
  Version: 1.0
  Author: Agbonghama Collins
  Author URI:

class Designmodo_contact_form {

    private $form_errors = array();

The contact form will be embedded in WordPress via shortcode [contact_form_dm].

The magic __construct() method handles the registration of the shortcode so it is recognizable by WordPress.

function __construct() {
// Register a new shortcode
add_shortcode('contact_form_dm', array($this, 'shortcode'));

The contact form HTML code will be in the static form() method.

static public function form() {
        echo '<form action="' . $_SERVER['REQUEST_URI'] . '" method="post">';
        echo '<p>';
        echo 'Your Name (required) <br/>';
        echo '<input type="text" name="your-name" value="' . $_POST["your-name"] . '" size="40" />';
        echo '</p>';
        echo '<p>';
        echo 'Your Email (required) <br/>';
        echo '<input type="text" name="your-email" value="' . $_POST["your-email"] . '" size="40" />';
        echo '</p>';
        echo '<p>';
        echo 'Subject (required) <br/>';
        echo '<input type="text" name="your-subject" value="' . $_POST["your-subject"] . '" size="40" />';
        echo '</p>';
        echo '<p>';
        echo 'Your Message (required) <br/>';
        echo '<textarea rows="10" cols="35" name="your-message">' . $_POST["your-message"] . '</textarea>';
        echo '</p>';
        echo '<p><input type="submit" name="form-submitted" value="Send"></p>';
		echo '</form>';

The validate_form method which accept the contact form values as it argument, will validate and ensure that:

  • No form field is unfilled or empty.
  • The sender name is not less than four characters.
  • The sender email is valid

To keep things simple and succinct, we will stick to the above validation rule. Below is the code for the validate_form method.

public function validate_form( $name, $email, $subject, $message ) {

        // If any field is left empty, add the error message to the error array
        if ( empty($name) || empty($email) || empty($subject) || empty($message) ) {
            array_push( $this->form_errors, 'No field should be left empty' );

        // if the name field isn't alphabetic, add the error message
        if ( strlen($name) < 4 ) {
            array_push( $this->form_errors, 'Name should be at least 4 characters' );

        // Check if the email is valid
        if ( !is_email($email) ) {
            array_push( $this->form_errors, 'Email is not valid' );

The send_email() method sanitize and send the mail to the administrator email address.

public function send_email($name, $email, $subject, $message) {

        // Ensure the error array ($form_errors) contain no error
        if ( count($this->form_errors) < 1 ) {

            // sanitize form values
            $name = sanitize_text_field($name);
            $email = sanitize_email($email);
            $subject = sanitize_text_field($subject);
            $message = esc_textarea($message);

			// get the blog administrator's email address
            $to = get_option('admin_email');

            $headers = "From: $name <$email>" . "\r\n";

            // If email has been process for sending, display a success message
            if ( wp_mail($to, $subject, $message, $headers) )
                echo '<div style="background: #3b5998; color:#fff; padding:2px;margin:2px">';
                echo 'Thanks for contacting me, expect a response soon.';
                echo '</div>';

Take note, mail will be sent to the blog administrator or owner’s email address programmatically retrieved by the WordPress get_option function. The send_email() method ensure there isn’t any contact-form generated error before sending the email.

Next is the process_functions method. This method call and process the form, validate_form, send_email methods.

public function process_functions() {
        if ( isset($_POST['form-submitted']) ) {

			// call validate_form() to validate the form values
            $this->validate_form($_POST['your-name'], $_POST['your-email'], $_POST['your-subject'], $_POST['your-message']);

            // display form error if it exist
            if (is_array($this->form_errors)) {
                foreach ($this->form_errors as $error) {
                    echo '<div>';
                    echo '<strong>ERROR</strong>:';
                    echo $error . '<br/>';
                    echo '</div>';

        $this->send_email( $_POST['your-name'], $_POST['your-email'], $_POST['your-subject'], $_POST['your-message'] );


Firstly, the method check if the contact-form has been submitted. If true, it call the validate_form to validate the form values and display the form generated message. The send_email is also called to send the email to the administrator.

Finally, the form to display the contact-form HTML form.

Earlier, we added a add_shortcode inside the magic __construct method to register the plugin shortcode to WordPress

add_shortcode('contact_form_dm', array($this, 'shortcode'));

The second argument passed to the function is the shortcode callback method shortcode(), which is called when the shortcode is used.

public function shortcode() {
        return ob_get_clean();


The class would be useless if it isn’t instantiated. Finally, we instantiate the class to put it to work.

new Designmodo_contact_form;

How To Use the Contact Form Plugin

To embed the contact form in WordPress posts or pages, use the shortcut [contact_form_dm], while in a theme template, use the code below:

<?php echo do_shortcode('[contact_form_dm]'); ?>

Below is a screenshot depicting a message has been successfully sent via the contact form.

Contact form


A lot of contact form plugins in the WordPress plugin repository are quite heavy and bloated. If you have been considering rolling out your own, this tutorial showed how to build a simple contact form. Here is the link to the designmodo contact-form plugin just in-case you want to use in your WordPress site and also study the code to learn how it works.

If you have any questions, or suggestions for code improvement, let me know in the comments.


  1. Muze Jun 23, 8:45 pm

    Plugins make me lazy and not willing to learn, I will force myself to create my own contact form and stop using ready made plugin. Thanks for sharing your knowledge

    • Vladi Jul 7, 12:51 pm

      They might make you lazy but you should consider security and best practice. Sanitization and validation are a bunch of stuff that have to be done and doing them over and over again for each site takes a crazy amount of time. Good plugins take this into account as well not just display 3 fields.

  2. Collizo4sky Jun 23, 11:19 pm

    I am glad you found this tutorial helpful.

    Don’t hesitate to let me know when you encounter any difficulty.

  3. Ryan Jul 5, 8:38 am

    For some reason this is not working for me… I tried adding for my index.php and my page.php. I also tried installing the plugin directly from the download with no changes made.

    The short code just shows the short code text it does not show the actual form.

    • Agbonghama Collins Jul 14, 12:50 pm

      Hi, this is a WordPress plugin and not a plugin for any PHP web application.

  4. Gidone Jul 28, 4:43 pm


    For some reason the thank you message is displaying at all time. When I submit the form it shows the thank you messages correctly with the blue div around it, but when I haven’t it shows just the thank you message.

    Do you know why this happens?

    • Gidone Jul 28, 4:57 pm

      I have managed to solve the issue. The problem was the 3x “echo” in the thank you message:

      echo ”;
      echo ‘Thanks for contacting me, expect a response soon.’;
      echo ”;

      Changed into:

      echo ‘Thanks for contacting me, expect a response soon.’;

      • Agbonghama Collins Aug 5, 8:16 pm

        Glad you figured out the cause of your problem.

        Let me know if you have any questions.

  5. Rob Aug 7, 6:39 pm

    I would love to use this instead of the bloated Contact Form 7. I’ve copied the code directly from the zip file into my own functions plugin, and it looks promising but I can’t seem to get it to work. I tired an alternative email, and entered test text but nothing is coming up in my inbox. Any ideas?

    Also, how to remove the always shown “thank you text”? I see Gidone suggested removing the other two echo lines, but that causes a fatal error.

    • Rob Aug 7, 6:40 pm

      I tried to post a link to the page but it kicked it off as spam. It’s frustratednerd com / contact if interested.

  6. Martynas Oct 10, 11:08 pm

    How I can import my own css file without http link?

    • Donna Ingram Jul 29, 2:53 am

      The easiest way is to create a style sheet purely for the plugin and upload it into the same folder. Then add before class Designmodo_contact_form –
      add_action( ‘wp_enqueue_scripts’, ‘safely_add_stylesheet’ );
      * Add stylesheet to the page
      function safely_add_stylesheet() {
      wp_enqueue_style( ‘prefix-style’, plugins_url(‘style.css’, __FILE__) );

  7. Attila Apr 19, 12:06 am

    Could you please help me, point me to the right direction how to implement datepicker (js), how to process, handle and take data out of it and include the chosen date into the email.

  8. ian Oct 11, 11:01 pm

    Thanks for the tutorial. Have 2 things I’m trying to figure out: where specifically in the code is the subject that appears in the recipient (I edited to deliver directly to an email address) subject line as I wish to have a fixed subject line. Second is if it’s simple to enable a feature to allow for the user to choose between multiple addresses for the form to be sent to?

  9. John S. Oct 16, 9:23 am

    When changing confirmation method from echo to a redirect using header(“Location: “) I get a problem with buffer flushing and generating “headers sent” error. It has to do with buffer exceeding 4kb size.

    Enabling unlimited buffering fixes the problem, but I wonder if there is a fix for the code which will make it work without changing php settings?

  10. Michael Feb 1, 4:49 pm

    Finally !

    A clean tutorial to create a contact form. It’s so good to see a well structured clean coded tutorial about a contact form. This allows me to avoid overkill plugins, thank you so much.

    If I may, 2 questions maybe (might be interesting for others too):

    1. if you press submit, the page is refreshed. I’m using a Bootstrap Modal as a success message. What is the best way to prevent the page from reloading and just showing the modal? In fact, the modal works fine, but then the page refreshes…

    2. a feature request: maybe include a recaptcha?

    Thanks for the great work.

    kind regards,


  11. Michael Feb 1, 9:02 pm

    Oh, found a bug:

    if someone refreshes the page, the form is send again :-(

Leave a Reply

* Minimum length: 20 characters