How to create a WordPress Plugin (Ajax Contact Form)

WordPress is a very popular CMS (Content Management System) use to create websites. It initially started out as a blogging platform but has evolved over the years. According to built with.com, WordPress has 50% of the entire CMS market. Personally, I am a Joomla fan, but I have come to appreciate WordPress and how easy it is, and specifically its support for PHP7 and HHVM, which Joomla lacks at the moment.

To create a WordPress plugin, you must have a basic understanding of PHP. PHP is very similar to other languages such as C++ and JAVA, so knowledge of those languages can be helpful too.

In this tutorial, we will create a WordPress contact form plugin that submits using AJAX and has Google Recaptcha2 to prevent spamming.

Here are a few things to note:
1) The contact form is styled using Bootstrap. You can style the form anyhow you like. I prefer bootstrap since it is common and very easy to use.
2) This plugin uses the Google Recaptcha API v2. To get your private and public key, click here to learn more about how to get a key for your domain. Remember, both the public and private keys work for only ONE domain.
3) This plugin uses the PHP Mail function. Most shared hostings should support it out of the box. For dedicated hosting, make sure you have configured mail sending in your php.ini file.
4) We fetch your admin email using the plugin. Make sure your WordPress admin email is correct else you will not receive any contact message.
5) The javascript uses the jQuery library. Check if jQuery is included with your template else you would have to add it separately.

We are using AJAX, which means we will need a javascript file and another PHP file to handle the form submission. You can embed the javascript file in the WordPress plugin file, but I prefer to separate it for simplicity sake. Due to separate files, we will use a WordPress function to get us the absolute URL of our file locations.

To start, let us create a folder in the plugins folder which we can find in the wp-content folder at the root of your WordPress installation. Let us call this folder myajaxcontactform. In this folder, let us create a file called myajaxcontactform.php. This file is where we will have the main WordPress plugin code. Inside our folder called myajaxcontactform, let us create another folder called includes. In the includes folder, we will create two files, submit.php and contactform.js. We will also need to get the absolute URLs of these files since we will need them.
Now let us get to our myajaxcontactform.php file and put this function into it:

function ajaxcontactform() {
    $submit_url = get_site_url() . '/wp-content/plugins/myajaxcontactform/includes/submit.php';
    $javascript_file = get_site_url() . '/wp-content/plugins/myajaxcontactform/includes/contactform.js';
    $admin_email = get_option( 'admin_email' );

    echo '<form action="" role="form" method="post" id="contact_form">';
    echo '<div id="name-group" class="form-group">';
    echo '<label for="name">Name:</label>';
    echo '<input class="form-control" type="text" name="name" >';
    echo '</div>';
    echo '<div id="email-group" class="form-group">';
    echo '<label for="email">Email:</label>';
    echo '<input class="form-control" type="email" name="email"  >';
    echo '</div>';
    echo '<div id="subject-group" class="form-group">';
    echo '<label for="subject">Subject:</label>';
    echo '<input class="form-control" type="text" name="subject" >';
    echo '</div>';
    echo '<div id="message-group" class="form-group">';
    echo '<label for="message">Message:</label>';
    echo '<textarea id="message" class="form-control" rows="10" name="message"></textarea>';
    echo '</div>';
    echo '<input class="form-control" type="hidden" name="admin_email" value="' . $admin_email . '" >';
    echo '<input class="form-control" type="hidden" name="url" value="' . $submit_url . '" >';
    echo '<div id="captcha-group" class="form-group">';
    echo '<label for="captcha">Captcha:</label>';
    echo '<div class="g-recaptcha" data-sitekey="YOUR-RECAPTCHA-PUBLIC-KEY-GOES-HERE"></div>';
    echo '</div>';
    echo '<button type="submit" class="btn btn-default">Send Message</button>';
    echo '</form>';

    echo '
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
';
    echo '
    <script src="' . $javascript_file . '" </script>
    ';
}

You can see that the form action value is empty, this is because we are going to submit the form using AJAX. Instead, we will pass the action value to a hidden field on the form called URL.

Make sure to get your site’s public key and fill it in the form.

We also get the admin email and pass it to the form as a hidden field, the same way we passed the submit URL.

Now let us write another function that initializes the plugin for WordPress:

function contactform_start() {
    ob_start();
    ajaxcontactform();
    return ob_get_clean();
}

Now we add a short code so that we can use the plugin on our WordPress page:

add_shortcode( 'my_ajax_contact_form', 'contactform_start' );

Great, now we are done with the main plugin file. Let us get contactform.js and paste this in there:

$(document).ready(function() {

  $('form').submit(function(event) {
      //clear any errors and the red inout boxes (bootstrap feature)
      $('.form-group').removeClass('has-error');
      $('.help-block').remove();
      // get the form data to be submitted
      var formData = {
          'name'              : $('input[name=name]').val(),
          'email'             : $('input[name=email]').val(),
          'subject'           : $('input[name=subject]').val(),
          'message'           : $('textarea#message').val(),
          'captcha'           :  $('#g-recaptcha-response').val(),
          'admin_email'       : $('input[name=admin_email]').val(),
      };
      //post using jquery ajax
      $.ajax({
          type        : 'POST',
          url         : $('input[name=url]').val(),
          data        : formData,
          dataType    : 'json',
          encode          : true
      })

      .done(function(response) {

          if ( ! response.success) {
              //append error messages from the PHP script and highting their respective input boxes (bootstrap feature)
              if (response.errors.name) {
                  $('#name-group').addClass('has-error');
                  $('#name-group').append('<div class="help-block">' + data.errors.name + '</div>');
                }
              if (response.errors.email) {
                  $('#email-group').addClass('has-error');
                  $('#email-group').append('<div class="help-block">' + data.errors.email + '</div>');
                }
              if (response.errors.subject) {
                  $('#subject-group').addClass('has-error');
                  $('#subject-group').append('<div class="help-block">' + data.errors.subject + '</div>');
                }
              if (response.errors.message) {
                  $('#message-group').addClass('has-error');
                  $('#message-group').append('<div class="help-block">' + data.errors.message + '</div>');
                }
              if (response.errors.captcha) {
                  $('#captcha-group').addClass('has-error');
                  $('#captcha-group').append('<div class="help-block">' + data.errors.captcha + '</div>');
              }


          }
          //if we are here, it means the message was posted successfully
          else {
            $('#contact_form').append('<p><div class="alert alert-success">' + data.message + '</div>');
          }
      });
      //prevent the form from posting using the usual method
      event.preventDefault();
  });

});

Now, let us grab our submit.php file and paste this code in there. This will process our javascript and send an email to the admin email address:

<?php
// declare data as an array
$data = [];

//check for post content, if no content, declare error messages
  if ( !isset($_POST["name"])) {
      $data['success'] = false;
            $data['errors']['name'] = 'Please enter your name.';
    }
  elseif ( !isset($_POST["email"])) {
      $data['success'] = false;
      $data['errors']['email'] = 'Please enter your email address.';
        }
  elseif ( !isset($_POST["subject"]) ) {
      $data['success'] = false;
      $data['errors']['subject'] = 'Please enter the subject of the message.';
        }
  elseif ( !isset($_POST["message"]) ) {
      $data['success'] = false;
      $data['errors']['message'] = 'Please enter the message you want to send.';
        }
  elseif (!isset($_POST["captcha"]) ) {
      $data['success'] = false;
      $data['errors']['captcha'] = 'Proof that you are human';
        }
        //validate email else throw error message
  elseif ( !filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
      $data['success'] = false;
      $data['errors']['email'] = 'Please chack your email address';
        }


        else{
      //sanitize POST values
      $name = strip_tags(trim($_POST["name"]));
      $name = str_replace(array("\r","\n"),array(" "," "),$name);
      $subject = strip_tags(trim($_POST["subject"]));
      $subject = str_replace(array("\r","\n"),array(" "," "),$subject);
      $email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);
      $admin_email = filter_var(trim($_POST["admin_email"]), FILTER_SANITIZE_EMAIL);
      $message = trim($_POST["message"]);
      $captcha=$_POST['captcha'];
      //verify the captcha (make sure to add your private key to the url without the parenthesis)
          $response=json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=​(Your-RECAPTCHA-PRIVATE-KEY-GOES-HERE)&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']), true);

              if($response ["success"]==false){
                     $data['errors']['captcha'] = 'Captcha failed. Please try again';
               $data['success'] = false;
          }
          //if we are here it means, everything was good so we can send the email
          else {
              $recipient = $admin_email;

              $email_subject = "New Contact from $name";

              $email_message = "Name: $name\n";
                  $email_message .= "Subject: $subject\n";
              $email_message .= "Email: $email\n\n";
              $email_message .= "Message:\n$message\n";

              $email_headers = "From: $name <$email>";

                if (mail($recipient, $email_subject, $email_message, $email_headers)) {
                    $data['message'] = "Thank You! We have received your message and we would get back to you soon.";
                          $data['success'] = true;
                } else {
                          $data['errors']['name'] = "Oops! Something went wrong and we couldn't send your message.";
                    }
            }
        }

//convert data array to json and echo the json content
    echo json_encode($data);
?>

That is it, as you can see, it is very easy to create a WordPress plugin. Mind you, this is just a simple plugin. To add more functionalities such as Admin settings, database access, etc., I’d advise that you learn more about the WordPress Plugin API, or you can also look at the WordPress plugin boilerplate, which provides us with an Object-oriented approach to developing WordPress plugins.

You can get the source code of the entire project on GitHub here.

 

4 Comments

  1. Oh my, nice work. Curious about the extra’s like admin settings and storing all sent forms into a custom post type. Maybe write an extra tutorial regarding that? I would love it.

  2. Michael Martens

    Mmm, bummer:

    contactform.js:1 Uncaught TypeError: $ is not a function
    at contactform.js:1
    (anonymous) @ contactform.js:1

    1. Hello Michael, that normally means you don’t have jquery loaded. Please make sure its available on the page you are working on. thanks

      1. Hi bro, I’m building my own plugin contact form with ajax, recaptcha, but I’ve errors, the data is save in the DB, but I need improve it on the validation fields with wordpress functions please help me

Leave a Reply

Your email address will not be published. Required fields are marked *