A common feature of many websites is a contact form. Standard contact forms work just fine, but you can make them nicer by using AJAX to submit the form data in the background.
In this blog post, you’re going to learn how to create a website contact form that submits the form data using AJAX. We’ll be using jQuery to help simplify the JavaScript code and a simple PHP mailer script to handle sending the form data via email.
Let’s get started.
Building the HTML Form
Your first task is to set up the HTML form that will collect data from the user. Give your <form>
element the ID ajax-contact
, set the method
attribute to post
, and the action
attribute to mailer.php
.
<form id="ajax-contact" method="post" action="mailer.php">
<div class="field">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="field">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="field">
<label for="message">Message:</label>
<textarea id="message" name="message" required></textarea>
</div>
<div class="field">
<button type="submit">Send</button>
</div>
</form>
Here you’ve set up a simple form that has fields to collect the user’s name, email address, and message. Notice that each of the form fields has a required
attribute. In browsers that support HTML5 form validation, this will prevent the form from being submitted until all the fields have been completed.
Next you need to create a <div>
element that will be used to display success and error messages to the user. Create this element above the <form>
in your HTML markup and give it the ID form-messages
.
<div id="form-messages"></div>
Now you need to download the code resources and copy the style.css
file into your project directory. You’ll also need to add a <link>
element that tells the browser to load the stylesheet.
<link rel="stylesheet" href="style.css">
Finally you need to create two <script>
elements that reference the jquery-2.1.0.min.js
and app.js
files. Add these just before the closing </body>
tag.
<script src="jquery-2.1.0.min.js"></script>
<script src="app.js"></script>
It’s important that you load the jquery-2.1.0.min.js
file first as the code within app.js
requires jQuery.
That’s all the HTML you’re going to need in this post. Next up, let’s take a look at the JavaScript.
Submitting the Form Using AJAX
Create a new file in your project directory called app.js
. This is going to contain all of the code responsible for submitting the form data using AJAX.
Copy the following code into the app.js
file.
$(function() {
// Get the form.
var form = $('#ajax-contact');
// Get the messages div.
var formMessages = $('#form-messages');
// TODO: The rest of the code will go here...
});
Here you’ve created two new variables, form
and formMessages
, that reference the corresponding elements in your HTML markup.
Next you need to create an event listener that will intercept submit
events on the form. You can do this using the jQuery submit
method.
// Set up an event listener for the contact form.
$(form).submit(function(event) {
// Stop the browser from submitting the form.
event.preventDefault();
// TODO
});
Here you’ve passed a function to the submit
method that will be executed when the user submits the contact form. You’ve also told the browser not to submit the form as it would normally by calling the preventDefault
method on the event.
Next you need to serialize the form data. This will convert the data the user has entered into the form into a key/value string that can be sent with the AJAX request. Use the jQuery serialize
method to serialize the form data and then store the result in a variable called formData
.
// Serialize the form data.
var formData = $(form).serialize();
Now you’re ready to write the code that’s responsible for sending the form data to the server and processing the response. Copy the following code into your app.js
file.
// Submit the form using AJAX.
$.ajax({
type: 'POST',
url: $(form).attr('action'),
data: formData
})
Here you’re using jQuery’s ajax
method to create a new AJAX request. You’ve passed an object to the ajax
method that contains a number of properties used to configure the request. The type
property specifies the HTTP method that will be used for the request, in our case POST
. The url
property is the location of the script that the form data will be sent to. You’ve populated this property by fetching the action
attribute from the form. Finally, the data
property has been populated using the formData
variable that you created earlier.
Next you need to handle a successful response from the server. Copy the following code directly after the closing bracket of the ajax
call. Note that I’ve deliberatly left out the semi-colon.
.done(function(response) {
// Make sure that the formMessages div has the 'success' class.
$(formMessages).removeClass('error');
$(formMessages).addClass('success');
// Set the message text.
$(formMessages).text(response);
// Clear the form.
$('#name').val('');
$('#email').val('');
$('#message').val('');
})
This done
method will be called if the request completes successfully. Here you first make sure that the formMessages
element has the success
class and then set the text content of this element using the data returned by the mailer script. To finish, you clear out the values from each of the form fields.
The last bit of JavaScript you need to write handles what should happen if an error occurs. Copy the following into app.js
.
.fail(function(data) {
// Make sure that the formMessages div has the 'error' class.
$(formMessages).removeClass('success');
$(formMessages).addClass('error');
// Set the message text.
if (data.responseText !== '') {
$(formMessages).text(data.responseText);
} else {
$(formMessages).text('Oops! An error occured and your message could not be sent.');
}
});
This fail
method is called if the mailer script returns an error. Here you first make sure that the formMessages
element has the error
class. You then check to see if the AJAX request returned any responseText
. If it did, you use this text to set the content for the formMessages
element; otherwise use a generic error message.
That completes the HTML and JavaScript code that’s needed to build an AJAX contact form. In the next section you’re going to learn about the mailer script that is responsible for processing the form data and sending out an email.
Creating the PHP Mailer Script
Now it’s time to write the PHP mailer script that will process the form data. This simple script is responsible for checking that the form data is valid and then sending out the email. If an error occurs, the mailer script will respond with an appropriate status code so that the JavaScript within the fail
callback you wrote earlier will be executed.
Create a new file called mailer.php
and copy into it the following code.
<?php
// Only process POST reqeusts.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Get the form fields and remove whitespace.
$name = strip_tags(trim($_POST["name"]));
$name = str_replace(array("\r","\n"),array(" "," "),$name);
$email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);
$message = trim($_POST["message"]);
// Check that data was sent to the mailer.
if ( empty($name) OR empty($message) OR !filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Set a 400 (bad request) response code and exit.
http_response_code(400);
echo "Oops! There was a problem with your submission. Please complete the form and try again.";
exit;
}
// Set the recipient email address.
// FIXME: Update this to your desired email address.
$recipient = "hello@example.com";
// Set the email subject.
$subject = "New contact from $name";
// Build the email content.
$email_content = "Name: $name\n";
$email_content .= "Email: $email\n\n";
$email_content .= "Message:\n$message\n";
// Build the email headers.
$email_headers = "From: $name <$email>";
// Send the email.
if (mail($recipient, $subject, $email_content, $email_headers)) {
// Set a 200 (okay) response code.
http_response_code(200);
echo "Thank You! Your message has been sent.";
} else {
// Set a 500 (internal server error) response code.
http_response_code(500);
echo "Oops! Something went wrong and we couldn't send your message.";
}
} else {
// Not a POST request, set a 403 (forbidden) response code.
http_response_code(403);
echo "There was a problem with your submission, please try again.";
}
?>
Update: Thanks to Aaron Traas for his modifications that make this mailer script more secure.
This script starts by checking that the request was sent using the POST
method. If it wasn’t, the script will return a 403
(forbidden) HTTP status code and an error message.
Once you’ve established that the correct HTTP method has been used you then extract the form data into three variables $name
, $email
, and $message
. You also use the PHP trim
method here to cut out any unwanted whitespace.
Next you will check to make sure that none of these variables is blank. If one or more is blank, set the response code to 400 (bad request) and return an error message to the browser.
Now that you’ve determined the data is clean, you prepare the email, first by creating a variable with the email recipient. You then create variables for the subject, email content, and finally the email headers.
Note: Setting the email headers is optional. Doing so will make the email appear as though it was sent by the person that filled out the form. However, it’s important to note that manipulating the headers like this can also cause the email to be marked as spam by some email clients.
Next you will attempt to send the email using the PHP mail
function. If this is successful, you will return a success message. If it’s not, you need to set the response code to 500
(internal server error) and return an error message.
Note: The standard PHP mail
function will do just fine for the purposes of this blog post, but there are more robust ways of sending email using PHP. If you’re interested in learning more, I recommend that you check out the Build a Simple PHP Application project on Treehouse.
That’s it! You’re all done.
Load up your HTML file in a web browser and try out the form. You’ll need to be using a web server with support for PHP and the mail
function for everything to work correctly.
Final Thoughts
In this blog post, you’ve learned how to create a contact form that uses AJAX to communicate with a mailer script on the server. You’ve used jQuery to help simplify the JavaScript code, but you could have achieved the same result with standard JavaScript.
Using AJAX within your websites allows you to improve the user experience in a number of different areas, not just contact forms. Next time you’re building a website, ask yourself how AJAX could help to create a smoother experience for your users.
Minor note: http_response_code() requires PHP >= 5.4, which is not necessarily standard on all servers. The current Ubuntu 12.04 LTS package, for example, has 5.3.
Thanks for picking that up AJ
What is the benefit of this method over using direct php post methods?
It allows you to submit form, without page reload.
Sounds cool.
Thanks
It’s useful thank you, it also easy to use
NICE !!
Hey Matt, do you by chance do development work per hour? If so, can you contact us? Need help with this and more.
I am getting a 500 error response code, even w/ the default files attached.
Any thoughts?
Hi Travis,
Which version of PHP do you have installed?
As AJ pointed out earlier in the comments, the mailer script will require version 5.4
If that’s not it, check your log files to see what error is being raised. Post the error message here and I’ll try to formulate a solution.
The overall technique is nice and clean and tidy, but the backend code is deficient. It is weak to many forms of injection attacks. Using:
$email = filter_var(@$_POST[’email’], FILTER_SANITIZE_EMAIL );
As the “from” email is specified in the header field of the mail function, commas and ; and other stuff can be injected to make the SMTP server do all kinds of weird things.
The PHP world is full of a lot of noobs that cut and paste scripts they find from Google searches that are full of nasty security holes.
Hi Aaron,
Thanks for the feedback.
Admittedly I’m not much of a PHP guy but I wanted to provide some idea of how this would work on the server-side rather than just calling a non-existing file.
You have a valid point about people copy and pasting this script for use in their own websites.
I’d be happy to update the post if you can provide a more secure version of the mailer script.
Thanks!
Matt
Here you go:
https://gist.github.com/AaronTraas/9533041
It’s easy to get yourself in trouble not knowing what you’re doing in PHP because PHP is so easy to pick up and find sample code for. I know because I’ve learned the hard way.
Thanks Aaron!
Tested, updated, and credited
Much obliged!
Note: I didn’t test the code; I’m at work and don’t have time for that. I’d recommend testing before posting.
Thanks for the tutorial, Matt!
I’m having one issue, though. While the email is sending correctly, the error message from within the fail() call in app.js is showing after sending (I ensured the wording differed in each error message across the JS and PHP files so I could tell which error was which). I verified that my syntax matched yours, and the error persists. This happens in Chrome 33 and Firefox 24. I am using PHP 5.3.26, so does it have something to do with mailer.php’s http_response_code() not working in < v5.4, as AJ Foster commented?
Hi Alex,
Yes, I suspect that’s what’s causing the problem.
Try setting the response header manually rather than using http_response_code().
Here’s an example:
header(“HTTP/1.0 404 Not Found”);
More info: http://uk1.php.net/manual/en/function.header.php
The status codes and names can be found in the code comments
Let me know how you get on.
Matt, you rock!!!
Although, for some reason, my success and error messages show up in a new page. I have my “form-messages” div at the bottom, next to my submit button, could that be the culprit?
Once again, thanks for this!
Hi Reme,
This sounds strange. Would you be able to share your code with me?
I’d be happy to take a look and see what’s going on
Hey Matt,
How would you want me to share it with you? On here or by email?
Appreciate your help!
Hey Matt,
I’ll gladly share my code with you. How would you want me to?
On here or by email?
Appreciate your help!
Happy to do either
You can reach me at matt.west [at] kojilabs.com if you prefer email.
Sent you an email.
Thanks for your help!
Much appreciated
Hi Matt,
Even i am having the same issue, the mail is sent and the response is going to a new page.
Can you help me with it.
Thanks & Regards,
Vishal S
I get this error even though the mail get sent:
Fatal error: Call to undefined function http_response_code() in /nfs/c08/h02/mnt/116936/domains/gimme-a-gig.com/html/mailer.php on line 40
Any solutions to this? I am clueless when it comes to PHP ;o)
Hi Glenn,
Looks like your version of PHP doesn’t support the http_response_code() function.
Try setting the response code manually. For example:
header(“HTTP/1.0 404 Not Found”);
More info: http://uk1.php.net/manual/en/function.header.php
Let me know how you get on
Hi Matt
Thanks for the help – I managed to use the latest version of PHP and it worked. I am a novice when it comes to PHP. Does header(“HTTP/1.0 404 Not Found”); replace http_response_code(200); in your solution? Just curious…
Good stuff!
Yep, the header() function would replace http_response_code().
Great tutorial, thank you, it also easy to use
im getting, error message : Oops! Something went wrong and we couldn’t send your message. seems like it fails at : ” if (mail($recipient, $subject, $email_content, $email_headers)) { … }”
I am trying to learn this method. Hope you can help.
Previously i received the error due to that status code. and i commented it. Any suggestions ?
Any advice on how to add a loading animation/GIF as the form is submitting? I have some forms that are taking about 10 seconds to post, before the success shows up. Would like to add an animated GIF next to the submit button to let the user know the form is still submitting. Thanks!
Hey Jon, Try This . . .
———
// Submit the form using AJAX.
$.ajax({
type: ‘POST’,
url: $(form).attr(‘action’),
data: formData,
beforeSend: function(){
form.prepend( formMessages.html(‘ Email is sending…’).fadeIn() );
}
})
———-
Where “beforeSend” creates your spinning image using Font Awesome’s spinner icon and spin function. This message is created inside the formMessages
Hi Matt, thank you for the ajax tutorial, can you plz give a link to full code?
Thanks for reading!
You can download the full code here: http://cl.ly/290k070a1m1Z
I’m trying to get AJAX to work, but the emails on my contact form do not go through. This error message comes up in the console:
POST 500 (Internal Server Error)
m.ajaxTransport.send @ jquery-1.11.3.min.js:5
m.extend.ajax @ jquery-1.11.3.min.js:5
(anonymous function) @ main.js:79
m.event.dispatch @ jquery-1.11.3.min.js:4
m.event.add.r.handle @ jquery-1.11.3.min.js:4
The “fail” function in my jquery causes the error message to show up in the formMessages div. So it looks like ajax is responding, but doesn’t send out the email…any idea why?
Hi Jessica,
Do you know which version of PHP you are running?
It sounds like a problem with the mailer script.
I tried running it on my website, online.
Jessica – the tutorial uses JQuery 2.1.0 while you are using 1.11.3
Try changing to 2.1.0, or if you are using 2.1.0, it could be you are loading two versions of JQuery.
This territorial is one of the better ones out there addressing the ideas around from submission without page refresh. As well nothing about it is hard coded; therefore is works perfectly as a function.
However, I am having an issue once the app.js file gets moved into a subdirectory or library. The code seems to break that that point and the form doesn’t submit. What is the code necessary if you move the jquery library and the app.js file into another directory within the root rather than where there are in this example, local to index.html?
I have tried all of the tricks and nothing appears to work.
Peter
Try changing to
But to make this work, the folder has to be in same place as your html file.
The code got formated :/
It should be: try changing <script src=”app.js”></script> to <script src=”folder/app.js”></script>.
^ as stated this solution doesn’t work. If I leave the file local to index.html, then the code executes and all works correctly.
However, if the file is moved to another folder, the code does not execute properly. True, the function is called, therefore the app.js is found in its new location; however, the response from malier.php is not passed back to index.html
I think that the problem might have something to do with passing the page name “mailer.php” through the function. please test it there and see if you don’t get the same result.
great code
thanks
I love this tutorial, and it seems clear in its instruction, however I myself am still having issues implementing the code. When hitting the submit button, and all required fields are filled out, the entire php file gets returned in the containing “form-messages”. If not filled out I get the js file’s fail error of “Oops! An error occurred…” just curious if there is something simple I may have done wrong. I even used your source code as a double check and get the same result.
Can help me in buliding my website http://blogswindow.com/ like yours…Please share tips with me
vsv
vcbcvbdff
Thanks for the tutorial. I was just wondering what and how the e-mail address is validated as it doesn’t accept just a few characters for example. Just wondering what it is that does that? thanks.
Matt West lives in a tree house. Go-o-o-o-o-o-o, Team!
This is a great contact form and have been using it on my site, I was wanting to add a couple of fields to this contact form and radio subject, and an file_uploader. is this possible?
Great tutorial!
I am trying to add html tags to the response messages. But the tags appear as text. I can’t get it to work. Do you know if it is possible to use html tags in the error/success messages?
Hey Matt,
thanks for this nice tutorial. It helped me by setting up my own tiny website!
Best
Chris
Hi Matt, really nice tutorial, thank you for this. Well laid out and easy to follow.
I am having a problem though. I have set it up and tested it, and the form is submitted and received by my email, but I am getting this message on my page once it has been sent.
Fatal error: Call to undefined function http_response_code() in /home/xxxxxx/public_html/privatelisting/mailer.php on line 40
What does this mean and how can I fix it? Many thanks!
Matt, just seen your other posts about this same issue. I have the most recent PHP version (5.6) and it’s still not working. Replacing it with header(“HTTP/1.0 404 Not Found”); doesn’t work, it just gives another error and the message doesn’t send at all now.
Could you possibly suggest another solution or one that I may understand?
Hi Chris,
What error do you get when you’re using the `header` method instead?
Matt, I have the same issue. I changed the header to header(“HTTP/1.0 404 Not Found”); and it give the same error message “There was a problem with your submission, please try again.” in your // Not a POST request, set a 403 (forbidden) response code comment.
Any idea how to stop messages being sent as spam?
Hi,
Thank you for this great tutorial. I used this contact form tutorial for two contact forms in my site.
One form was a mailing list and one a standard contact form. When the site went live the mailing list worked but the contact form was coming up with a 500 (internal server error) response code. Now they are both not working. They worked fine when I tested them on the local server.
My host says it is because they don’t support the php mail function anymore. Is there anyway around this? I’m a bit stuck.
Thanks Clare
Hi . Thanks for conveying your eloquent and simple
Thanks for the tutorial! I have a question about URL validation.
If my HTML page had a text input called URL, where someone could paste a URL, what would the correct syntax be in mailer.php (around Line 14, I presume) to validate the URL? Or should it just be treated like a string, and submitted as long as it’s not blank? I can’t seem to find information on this online.
Thanks again.
Hi. thanks.
Running into an issue where the form validates and the success message pops up, but the mail only actually sends some of the time. Tried recreating it with different email addresses and cannot recognize a pattern.
Currently running PHP 5.6. Does this sound like a host issue?
Hi guys,
I am fairly new to JavaScript and jQuery and I want to find out if I have indented and put all my code in the correct places: My JavaScript is below:
$(function() {
// Get the form.
var form = $(‘#ajax-contact’);
// Get the messages div.
var formMessages = $(‘#form-messages’);
// TODO: The rest of the code will go here…
$(form).submit(function(event) {
// Stop the browser from submitting the form.
event.preventDefault();
// TODO
});
// Serialize the form data.
var formData = $(form).serialize();
// Submit the form using AJAX.
$.ajax({
type: ‘POST’,
url: $(form).attr(‘action’),
data: formData
})
.done(function(response) {
// Make sure that the formMessages div has the ‘success’ class.
$(formMessages).removeClass(‘error’);
$(formMessages).addClass(‘success’);
// Set the message text.
$(formMessages).text(response);
// Clear the form.
$(‘#name’).val(”);
$(‘#email’).val(”);
$(‘#message’).val(”);
})
.fail(function(data) {
// Make sure that the formMessages div has the ‘error’ class.
$(formMessages).removeClass(‘success’);
$(formMessages).addClass(‘error’);
// Set the message text.
if (data.responseText !== ”) {
$(formMessages).text(data.responseText);
} else {
$(formMessages).text(‘Oops! An error occured and your message could not be sent.’);
}
});
});
In fact you get many more benefits other than the possibility of profit by
uploading blogging software to your web space (I am now going to use
the term ‘website’ for web space since that is more familiar to most people, though the terms mean different things).
You will be writing and researching about this topic a great deal if you want your blogging empire to succeed.
You can make security as critical as having enjoyment when it arrives to scooter-riding.
Just stopped by to give you some kudos, this tutorial is great and is exactly what I was looking for after 3 days of php torture.
Very appreciated!
Hi,
Thanks for the great tutorial.
I used your code on my server and its working great. However when i inserted in a wordpress page its giving problem. Form is submitting but i am getting error message. If problem is with php version it should not work in other folder also. But its working perfectly in other folder. What could be the reason?
Is it possible due to javascript conflict with older version of jquery on the same page?
First thank you for this good tutorial.
Now i am want to ask about the security about this form. Aren t there robots looking for buttons tags to press and send spam? Is there any way to solve this?
Hi,
I’ve implemented all javascript and php and the browser is bringing up the #form-messages as green and showing the success message, but I am not receiving the email. I have changed the recipient email in mailer.php, so I’m not sure what the issue is here…
Any help would be appreciated!
*Note: I’m running the page through MAMP Version 2.1.3 (2.1.3)
Update: I uploaded it to a remote server and it seems to have resolved the issue. The localhost seems to have had an problem with the code for some reason.
Anyway, problem solved
Thanks for a great tutorial!
Hi! I implemented this form on my website and everything works great, I get the emails, awesome, but my message appears on another page instead of in the same page which is how I wanted it. Any suggestions on how to fix this issue?
Hi,
The form is not submitting. Keep getting the 403 forbidden response. I even loaded the exact copies of your files on the production server and still get the same error. My server has PHP 5.3. I’ve replaced the header http_response_code(403); to header(“HTTP/1.0 404 Not Found”); and the form is not submitting and giving the 403/404 message.
Try this solution:
http://stackoverflow.com/questions/3258634/php-how-to-send-http-response-code