Creating a Simple Contact Form for Simple Needs


Whether you're starting a simple blog, creating a corporate website or building a creative portfolio with WordPress, a "Contact (Us)" page is (almost) always necessary and it's (almost) always better to have a contact form instead of sharing your e-mail address publicly (spam robots love them, though). Of course, there are plenty of great contact form plugins for WordPress but why bloat up the website with heavy plugins with lots of database queries, when we can use just a lovely, simple custom shortcode plugin instead?

Benefits of Building Your Own Contact Form

Plugins are awesome, but too many of them with lots of functionality you don't need can bloat up your website by using database connections, running extra PHP code, adding CSS stylesheets and JS files to your header... so, at some point, you just want to stay away from existing plugins, regardless of how awesome the plugin is that you want to use.

If you don't know how to code, I must admit that your hands are (kind of) tied and you're bound to use plugins. But if you're familiar with WordPress development at any level (and I'm assuming that you are, since you're still with me) then you should consider the benefits of hacking your own theme or coding your own plugin. Here are the advantages in my mind:

  • Optimization - Using too much code, especially extra code you don't need, can even push your hosting plan's limits in some cases. But even if you have plenty of resources on your server, optimization is always good for your website's health.
  • Cleanliness - Apart from the health of the server, cleaner code can be a huge benefit for your website loading & parsing speed. By coding/hacking on your own, you just use what you need and don't have to load tons of stuff in order to utilize a simple functionality on your website. It's even good for SEO, you know.
  • The joy of taking control - You should never underestimate the power of calling the shots. Taking control on your website definitely makes you a more enthusiastic designer/developer than using a bunch of ready-made code. That's why, even though we provide the full code for those who don't want to, I personally think that you should not copy/paste the code here but write it yourself. Even if you type exactly the same code, you could see how the plugin works and you feel the delight of taking control. Seriously.

The Code

All right, enough with the chit-chat - let's start coding! We're not going to deal with huge amounts of code or any kind of hard work here, so even if you're a beginner at PHP and/or WordPress, you can understand the code by following my lead and researching any part of the code that you don't recognize.

It's possible to put this code directly to your theme's functions.php file, but a better way to go is using it as a plugin. This way when you switch themes, you don't lose functionality and end up with shortcodes being printed in your content. Let's start with the standard plugin information:

Plugin Name: Simple Contact Form Shortcode
Plugin URI:
Description: A simple contact form for simple needs. Usage: <code>[contact email="your@email.address"]</code>
Version: 1.0
Author: Barış Ünver
Author URI:

// This line of comment holds the place of the amazingly simple code we're going to write. So you don't really need to read this.


A Tiny Helper Function: get_the_ip()

As you can guess from the name of the function, we're getting the real IP address of the user, even if the user is connecting through a proxy server. It's not bulletproof, of course, but we're going to use this as an extra bit of information from the user anyways.

Basically, we're going to try to get the different $_SERVER variables: HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP and REMOTE_ADDR, respectively. Here's the code:

function wptuts_get_the_ip() {
	if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
	elseif (isset($_SERVER["HTTP_CLIENT_IP"])) {
		return $_SERVER["HTTP_CLIENT_IP"];
	else {
		return $_SERVER["REMOTE_ADDR"];

The Shortcode

If you follow my posts here on Wptuts+, you know that I absolutely love WordPress' Shortcode API.

I'm going to divide the shortcode into 3 sections to be able to explain it better, but let's not forget to open and close the shortcode function first:

function wptuts_contact_form_sc( $atts ) {

	// This line of comment, too, holds the place of the brilliant yet simple shortcode that creates our contact form. And yet you're still wasting your time to read this comment. Bravo.

add_shortcode( 'contact', 'wptuts_contact_form_sc' );

Attributes of Our Shortcode

We need to set a few attributes in order to stay flexible while still being lightweight. Here's ten:

extract( shortcode_atts( array(
	// if you don't provide an e-mail address, the shortcode will pick the e-mail address of the admin:
	"email" => get_bloginfo( 'admin_email' ),
	"subject" => "",
	"label_name" => "Your Name",
	"label_email" => "Your E-mail Address",
	"label_subject" => "Subject",
	"label_message" => "Your Message",
	"label_submit" => "Submit",
	// the error message when at least one of the required fields are empty:
	"error_empty" => "Please fill in all the required fields.",
	// the error message when the e-mail address is not valid:
	"error_noemail" => "Please enter a valid e-mail address.",
	// and the success message when the e-mail is sent:
	"success" => "Thanks for your e-mail! We'll get back to you as soon as we can."
), $atts ) );

Remember that we're going to reference them in our code as a variable with the attribute's name (e.g. $label_submit).

E-Mailing the E-Mail

This is the most important part of the function, so I'll go ahead and explain the code inside the code, with comment lines:

// if the <form> element is POSTed, run the following code
	$error = false;
	// set the "required fields" to check
	$required_fields = array( "your_name", "email", "message", "subject" );

	// this part fetches everything that has been POSTed, sanitizes them and lets us use them as $form_data['subject']
	foreach ( $_POST as $field => $value ) {
		if ( get_magic_quotes_gpc() ) {
			$value = stripslashes( $value );
		$form_data[$field] = strip_tags( $value );

	// if the required fields are empty, switch $error to TRUE and set the result text to the shortcode attribute named 'error_empty'
	foreach ( $required_fields as $required_field ) {
		$value = trim( $form_data[$required_field] );
		if ( empty( $value ) ) {
			$error = true;
			$result = $error_empty;

	// and if the e-mail is not valid, switch $error to TRUE and set the result text to the shortcode attribute named 'error_noemail'
	if ( ! is_email( $form_data['email'] ) ) {
		$error = true;
		$result = $error_noemail;

	if ( $error == false ) {
		$email_subject = "[" . get_bloginfo( 'name' ) . "] " . $form_data['subject'];
		$email_message = $form_data['message'] . "\n\nIP: " . wptuts_get_the_ip();
		$headers  = "From: " . $form_data['name'] . " <" . $form_data['email'] . ">\n";
		$headers .= "Content-Type: text/plain; charset=UTF-8\n";
		$headers .= "Content-Transfer-Encoding: 8bit\n";
		wp_mail( $email, $email_subject, $email_message, $headers );
		$result = $success;
		$sent = true;
	// but if $error is still FALSE, put together the POSTed variables and send the e-mail!
	if ( $error == false ) {
		// get the website's name and puts it in front of the subject
		$email_subject = "[" . get_bloginfo( 'name' ) . "] " . $form_data['subject'];
		// get the message from the form and add the IP address of the user below it
		$email_message = $form_data['message'] . "\n\nIP: " . wptuts_get_the_ip();
		// set the e-mail headers with the user's name, e-mail address and character encoding
		$headers  = "From: " . $form_data['your_name'] . " <" . $form_data['email'] . ">\n";
		$headers .= "Content-Type: text/plain; charset=UTF-8\n";
		$headers .= "Content-Transfer-Encoding: 8bit\n";
		// send the e-mail with the shortcode attribute named 'email' and the POSTed data
		wp_mail( $email, $email_subject, $email_message, $headers );
		// and set the result text to the shortcode attribute named 'success'
		$result = $success;
		// ...and switch the $sent variable to TRUE
		$sent = true;

The Contact Form

This part is, of course, as important as the previous part. After all, how can the previous code send an e-mail if there's no contact form? :)

// if there's no $result text (meaning there's no error or success, meaning the user just opened the page and did nothing) there's no need to show the $info variable
if ( $result != "" ) {
	$info = '<div class="info">' . $result . '</div>';
// anyways, let's build the form! (remember that we're using shortcode attributes as variables with their names)
$email_form = '<form class="contact-form" method="post" action="' . get_permalink() . '">
		<label for="cf_name">' . $label_name . ':</label>
		<input type="text" name="your_name" id="cf_name" size="50" maxlength="50" value="' . $form_data['your_name'] . '" />
		<label for="cf_email">' . $label_email . ':</label>
		<input type="text" name="email" id="cf_email" size="50" maxlength="50" value="' . $form_data['email'] . '" />
		<label for="cf_subject">' . $label_subject . ':</label>
		<input type="text" name="subject" id="cf_subject" size="50" maxlength="50" value="' . $subject . $form_data['subject'] . '" />
		<label for="cf_message">' . $label_message . ':</label>
		<textarea name="message" id="cf_message" cols="50" rows="15">' . $form_data['message'] . '</textarea>
		<input type="submit" value="' . $label_submit . '" name="send" id="cf_send" />

Tip: If you looked carefully at the HTML code of the contact form, you probably saw the extra $subject variable. Remember the shortcode attribute 'subject' with no default value? This means that you can use the shortcode like this, if you want to set a default subject: [contact subject="Job application"]

The return of the Shortcode

This last bit is pretty simple: Show the success message if the e-mail is sent, or the e-mail form and the error message (if there is one). Here's the code:

if ( $sent == true ) {
	return $info;
} else {
	return $info . $email_form;

We're not showing the form again if the e-mail is sent, but if you want to show it anyways, you could use this simple line instead:

return $info . $email_form;


Of course, the code by itself wouldn't look great. With some make-up, CSS, we can make our form prettier. Add these lines of CSS code into your style.css file of your theme:

.contact-form label, .contact-form input, .contact-form textarea { display: block; margin: 10px 0; }
.contact-form label { font-size: larger; }
.contact-form input { padding: 5px; }
#cf_message { width: 90%; padding: 10px; }
#cf_send { padding: 5px 10px; }

If you did everything right, you will see something similar to the image below:

Screenshot of our contact form

Congratulations, you just built your own contact form shortcode!


This simple contact form is adequate for most websites but if you want to add more fields to it, you just need to edit the form and add the $form_data['name_of_the_new_field'] variables into the $email_message variable (and maybe add the field's name to the $required_fields array.

If you have any ideas on how to improve this code or show your website pages where you used it, please share your comment with us below!