Building The Ultimate Contact Form: A Step By Step Guide

Building The Ultimate Contact Form: A Step By Step Guide

When we talk about contact forms, mostly we stress on PHP functionality and forget about using or combining other techniques that can lift user experience.

We all have experienced the old school websites where you filled up the complete form, but due to a bad mistake you have to repeat the whole process. We will eliminate such situations in a modern way using AJAX. Though, AJAX can do many interesting things, but it is big in this scenario.

In this tutorial, you will learn how to build a contact form, securing it with Captcha, processing using AJAX and finally validating and sending it with PHP.

I hope you have some experience with PHP. If not, then please read about how to setup a PHP development environment before you proceed. I won’t go much into the setup, Rather I will keep my focus aligned to PHP scripts and AJAX.

Build A Contact Form Tutorial

Let’s get started.

Your first task is to download and make ready with the following and place them as shown in the directory structure:

  1. jQuery library (either call from CDN or download from the official site)
  2. PHP development environment (I prefer MAPP for Mac or WAMP server for Windows)
  3. A cup of coffee (optional)

Directory Structure

Building An HTML Form Skeleton (index.html)

This is a simple HTML form structure which is self-explanatory, but has a few things that need some ground to understand.

<div class="form-container">
        <form action="inc/mailer.php" id="contactForm" method="post" name="contactForm">
            <fieldset>
                <div>
                    <input id="contactName" name="contactName" placeholder="Name_" size="35" type="text" value="">
                </div>

                <div>
                    <input id="contactEmail" name="contactEmail" placeholder="Email_" size="35" type="email" value="">
                </div>

                <div>
                    <textarea cols="5" id="contactMessage" name="contactMessage" placeholder="Message_" rows="5"></textarea>
                </div>
                <div>
                    <img src="inc/captcha.php" id="captcha">
                </div>

                <div>
                    <input type="text" name="captchaCode" id="captchaCode" placeholder="Captcha_" style="float:right;">
                </div>
                <div>
                    <a href="#" onclick="document.getElementById('captcha').src='inc/captcha.php?'+Math.random();" id="changeImage">Not readable?</a>
                </div>
                <div>
                    <!-- contact-warning -->

                    <div id="message-warning">
                        Error boy
                    </div>
                    <button class="submit">Send /button> 
                </div>
            </fieldset>
        </form>
        <!-- Form End -->
        <!-- contact-success -->
        <div id="message-success">Your message was shipped, Relax!
            <br>
        </div>

    </div>

In this form, the action attribute is set to our main PHP file which will validate and process form information, also we are showing a Captcha image and a link which reloads the image if it is too vague to answer. Don’t worry about the Captcha generating code, it is easy to understand and we will look at it soon.

Adding Meat to the Skeleton (style.css)

Use the stylesheet to make your form beautiful and visually appealing. Once you have finished with it, we will jump to the AJAX part which is easy yet powerful.

.form-container {
    width: 700px;
    background: none repeat scroll 0 0 rgba(255, 255, 255, 0.6);
    margin-bottom: 70px;
    padding: 40px;
    position: relative;
    margin: 0 auto;
}

.form-container fieldset {
    border: solid 1px #e9f0f3;
    border-radius: 4px;
}

.form-container input {
    background: none repeat scroll 0 0 transparent;
    border: 1px solid #d9d9da;
    color: #3f3f46;
    float: left;
    font-size: 14px;
    margin: 15px auto;
    padding: 20px;
    width: 48%
}

.form-container input:focus,
.form-container textarea:focus {
    background: #F2FFAD
}

.form-container textarea {
    background: none repeat scroll 0 0 transparent;
    border: 1px solid #d9d9da;
    color: #3f3f46;
    font-size: 16px;
    margin: 15px auto;
    padding: 20px;
    width: 100%
}

.form-container button {
    background: #69c773;
    width: 100%;
    margin: 15px auto;
    padding: 20px;
    border-radius: 3px;
    border: none;
    color: #fff;
    font-size: 20px;
    cursor: pointer;
    font-size: 16px;
    text-transform: uppercase;
    font-weight: 700;
    box-shadow: 0 3px 0 #498b50;
}

.form-container button:hover {
    background: #64B96D;
    cursor: pointer;
}

.form-container input[type="email"] {
    float: right
}

#message-warning {
    background: #FF6F6F;
    display: none;
    font-size: 16px;
    margin: 5px auto;
    padding: 20px;
    text-align: center;
    color: #fff;
    clear: both;
}

#message-success {
    background: #6BD57E;
    color: #fff;
    display: none;
    font-size: 16px;
    margin: 5px auto;
    padding: 20px;
    text-align: center
}

#message-warning i,
#message-success i {
    margin-right: 10px
}

::-webkit-input-placeholder {
    color: #3f4047;
    font-size: 14px;
}

:-moz-placeholder {
    /* Firefox 18- */
    color: #3f4047;
    font-size: 14px;
}

::-moz-placeholder {
    /* Firefox 19+ */
    color: #3f4047;
    font-size: 14px;
}

:-ms-input-placeholder {
    color: #3f4047;
    font-size: 14px;
}

.form-container #captcha {
    color: #3f3f46;
    float: left;
    font-size: 14px;
    margin: 15px auto;
    height: 60px;
    width: 170px;
    text-align: center;
    background: none repeat scroll 0 0 transparent;
    border: 1px solid #d9d9da;
    padding: 18px 10px 10px 40px;
}

.form-container #changeImage {
    color: #3f3f46;
    float: left;
    font-size: 14px;
    width: 48%;
    margin-bottom: 15px;
    clear: both;
}

At this time, you should have following output in your browser.

After CSS

Bringing AJAX in to the Picture (script.js)

Take a deep breath! You have done a fantastic job so far.

    $('.form-container button.submit').click(function () {

        var contactName = $('#contactForm #contactName').val();
        var contactEmail = $('#contactForm #contactEmail').val();
        var contactMessage = $('#contactForm #contactMessage').val();

        var data = 'contactName=' + contactName + '&contactEmail=' + contactEmail + '&contactMessage=' + contactMessage + '&captchaCode=' + $("#captchaCode").val();

Here we are collecting the form data as soon as the user clicks on the submit button. We are storing this data into variables and then we will store all in one data object format.

Now, we are ready to send the data submitted by the user using AJAX. Here we have typical functions and settings.

The type setting is nothing but an alias of method. As we are processing data, so we have used POST . In the case of retrieving data from the server then we would have used GET method.

        $.ajax({

            type: "POST",
            url: "inc/mailer.php",
            data: data,
            beforeSend: function() {
                $('.submit').html('Sending...');
            },
            success: function (msg) {

                // Message was sent
                if (msg == 'OK') {
                    $('#message-warning').hide();
                    $('#contactForm').fadeOut();
                    $('#message-success').fadeIn();
                }
                // There was an error
                else {
                    $('#message-warning').html(msg);
                    $('#message-warning').fadeIn();
                    $('.submit').html('Failed, Try Again!');
                }

            }

        });
        return false;
    });

url needs a string value where the request is sent. In our case, it’s our PHP file called mailer.php located inside the inc folder.

data can be a plain object, string or array to be sent to the server. In this part we will send our data that we have already transformed into the data object.

beforeSend is one of the callback hooks in jQuery. It is important from the perspective of user experience. Here, we are changing text on the button before we get the response from the server. We have used it as visual feedback to the user that the data is processing.

success is another callback function which is executed when we successfully received response from the server. So, our code says that if we get response ‘OK’ from our file mailer.php then we will execute the following lines of code or a few lines of code that will make your users disappointed will get executed.

Bonus tip: You can play with beforeSend callback such as showing loading bar before you get response and hide it once you get a response or an error.

Generating strings which are easy for humans and tough for computers captcha.php

I hope that you have understood so far. Let’s now investigate the file below, which generates a Captcha image for us.

session_start();
	
	$string = '';
	
	function generateCode($characters) {
		/* list all possible characters, similar looking characters and vowels have been removed */
		$possible = '0123456789BCDGHJKMNPQRSTUVWXYZ@#&%!bcdghjkmnpqrstuvwxyz';
		$code = '';
		$i = 0;
		while ($i < $characters) { 
			$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
			$i++;
		}
		return $code;
	}
	
	$characters=7; // number of characters to display
	$string = generateCode($characters);	
	
	$_SESSION['randomCode'] = $string;
	

As per PHP.net manual, session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.

We will need it so that other scripts can know what the correct code is and validates that it’s been entered correctly.

$string variable will hold our Captcha string and the same will be used on the image. We have declared one variable $characters which holds the number of characters we want to show on the Captcha image.

We invoke generateCode() function and pass $characters as a parameter. Inside the function, we have defined a variable called $possible.

$possible is your tool to make your Captcha a cocktail of characters. I have removed a few similar looking characters and added a few special characters. I have kept the length of string to seven (Pssst, it’s my lucky number).

A while loop will iterate to $characters times and append each character to $code to form a complete string of seven characters. This will be stored in the $string variable.

We will store $string into a session variable so we can make use of it in mailer.php file.

$fontDir = '../fonts/'; // font folder
	
	$image 			= imagecreatetruecolor(250, 60);
	
	$textColor 		= imagecolorallocate($image, 63,63,70); // give as RGB color
	$imageBgColor 	= imagecolorallocate($image, 255, 255, 255);
	
	imagefilledrectangle($image,0,0,399,99,$imageBgColor);
	imagettftext ($image, 30, 0, 10, 40, $textColor, $fontDir."OpenSans-Regular.ttf", $_SESSION['randomCode']);
	
	header("Content-type: image/png");
	imagepng($image);

I would suggest you to keep your font (only TrueType Font file) vague because it is for security purposes and not a place to show your typography skills (just kidding), but you can show your color skills, you can change the background as well text color of the image to suit your website’s color scheme.

Shipping Valid Contact Information into the Inbox mailer.php

Take a chill beer! We are about to complete our tutorial. At this point in time, you have done an amazing job. Now, you have a contact form with a Captcha. It’s time to connect the last dot.

The first thing we will do here is to get the entire form field and sanitize them by removing white spaces.

session_start();

// Replace this with your own email address
$siteOwnersEmail = 'yourname@domain.com';

if($_POST) {
   // Get the form fields and remove whitespace.
   $name = trim(stripslashes($_POST['contactName']));
   $email = trim(stripslashes($_POST['contactEmail']));
   $subject = "New Contact form Submission";
   $contact_message = trim(stripslashes($_POST['contactMessage']));
   @$captcha = $_POST['captchaCode'];
   @$random = $_SESSION['randomCode'];

In the next set, we will put our validation. So, in this scenario, the name field must be more than two characters, we have also defined a regular expression for email (by the way, you can take advantage of HTML5 form attributes such as type=email for email validation).

   // Check Name
	if (strlen($name) < 2) {
		$error['name'] = "Please enter your name.";
	}
	// Check Email
	if (!preg_match('/^[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*+[a-z]{2}/is', $email)) {
		$error['email'] = "Please enter a valid email address.";
	}
    
    //check captcha code
	if($captcha !== $random || $captcha='' ) {
	   $error['captcha'] = "Please verify that you typed in the correct code captcha.";
		}
    
	// Check Message
	if (strlen($contact_message) < 15) {
		$error['message'] = "Your message should have at least 15 characters.";
	}
    
   // Subject
	if ($subject == '') { $subject = "Contact Form Submission"; }

We have also validated the message to be at least fifteen characters. All these validations can be varying from a use case to use case and one’s personal preference. The rest is standard PHP mailer script.

   // Set Message
   @$message .= "Email from: " . $name . "<br />";
	$message .= "Email address: " . $email . "<br />";
   $message .= "Message: <br />";
   $message .= $contact_message;
   $message .= "<br /> ----- <br /> This email was sent from your site's contact form. <br />";

   // Set From: header
   $from =  $name . " <" . $email . ">";

   // Email Header

	$headers = "From: " . $from . "\r\n";
	$headers .= "Reply-To: ". $email . "\r\n";
 	$headers .= "MIME-Version: 1.0\r\n";
	$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";


   if (@!$error) {

      ini_set("sendmail_from", $siteOwnersEmail); // for windows server
      $mail = mail($siteOwnersEmail, $subject, $message, $headers);

		if ($mail) { echo "OK"; }
      else { echo "Something went wrong. Please try again.";  }
		
	} # end if - no validation erro

	else {

		$response = (isset($error['name'])) ? $error['name'] . "<br /> \n" : null;
		$response .= (isset($error['email'])) ? $error['email'] . "<br /> \n" : null;
		$response .= (isset($error['message'])) ? $error['message'] . "<br />" : null;
		$response .= (isset($error['captcha'])) ? $error['captcha'] . "<br />" : null;
		echo $response;

	} # end if - there was a validation error

}

So, if the $_POST is true and all the form fields satisfy the validation then we will get an ‘OK’ message which we have used in our JS file else we will get errors instantly.

You don’t need to worry about email configuration as this will be done by the server. So, you need to only connect these pieces and bingo!

Conclusion

I hope I achieved your ideal with providing all the must haves that a modern contact form should have. I know there is much to cover, so I opened that up for you. You can extend and make the mailer script more secure and robust by adding filters and other fancy stuff.

Do you have anything in mind that can improve this tutorial? Share your reaction in the comments section if you have something to share or decide to use it for one of your projects or sites.

Deals

Iconfinder Coupon Code and Review

Iconfinder offers over 1.5 million beautiful icons for creative professionals to use in websites, apps, and printed publications. Whatever your project, you’re sure to find an icon or icon…

WP Engine Coupon

Considered by many to be the best managed hosting for WordPress out there, WP Engine offers superior technology and customer support in order to keep your WordPress sites secure…

InMotion Hosting Coupon Code

InMotion Hosting has been a top rated CNET hosting company for over 14 years so you know you’ll be getting good service and won’t be risking your hosting company…

SiteGround Coupon: 60% OFF

SiteGround offers a number of hosting solutions and services for including shared hosting, cloud hosting, dedicated servers, reseller hosting, enterprise hosting, and WordPress and Joomla specific hosting.