Using AJAX In Your WordPress Theme Admin

Update: 3/06/2012

I’ve added a small description about get_option() as a lot of people were confused about what it does.

I recently recieved an e-mail asking if I could help make an admin for a theme that was powered by AJAX & therefore did not need the page to be refreshed to save the data. Unfortunately I couldn’t help as although I have built admins for plugins & themes before, I didn’t have the knowledge to add the AJAX functionality to it. However I’ve spent the past day or so reading & trying to understand the theory behind AJAX usage within WordPress’ admin & I think I’ve managed to come up with something.

Good For You! How Does That Help Me?

Well I wanted to understand it so I could write a simple tutorial for those who are getting into theme development & want to add that little bit of ‘je ne sais quoi’ to the admin of a theme.

So How Do We Start?

We add our admin page link to WordPress’ menu. Since we are going to add code into the header we need to do a few things different to a normal admin page or the header code will be output to all of the pages in the WordPress admin. Exactly what we don’t want since it is useless for anything other than running our admin page.

Here is the code to add your page into the WordPress admin:

First we call add_action() this tells WP to run a function into the admin_menu hook. The function test_add_theme_page, change the name if you like (just make sure they match), checks that the admin page we are on is actually the current file. If it is, we can add the code into the header (code coming in a minute) using the admin_head hook. No matter what page we are on we still need to add the link for the admin page into the admin menu so we run the function add_theme_page(). I explained the useage in my other tutorial, but just in case here it is again.

__(‘Test Admin’)
This is the text shown as the browser title, that’s the text shown in the title bar of your browser.
__(‘Test Admin’)
This is the text shown as the link title in the WordPress menu. It will appear under the Appearance tab
This is the role required to access the page.
This is a unique identifier. I’ve used the current file’s filename.
The function that will create the contents of the options page.

Adding the jQuery

As I mentioned earlier add_action('admin_head', 'test_theme_page_head'); adds code into the header of the page. This is what we will use to add our jQuery code. Here is the function I have used:

Ok, I’m going to attempt to explain everything written here. It might take a while so bare with me. :lol:

First we define the function we named in our add_action() call. We then break out of PHP so we can easily add our jQuery code. We open a script tag as normal, then we start our jQuery with a standard run on DOM load. I’ve passed the $ through the run on DOM function so you should be able to use the standard $ inside it, however I chose to continue using the jQuery that WordPress defines for conflict prevention with other JS libraries.

Next we target our form, which hasn’t been made yet, so pick an ID or something here for it, and attach a function to it’s submit event. We serialize the data from the form, this excludes the submit buttons value & encodes data in standard URL query format, storing it in the variable data. We can use jQuery(this) because we are inside the element that is holding the data, in this case the form. Next we create a standard AJAX call using jQuery’s function. ajaxurl is a javascript global variable defined by WordPress & should always be used for AJAX requests inside WordPress for security reasons. data is our serialized form data & the the function is to be ran on the completion (callback) of our AJAX request. response is the data returned from the AJAX request.

Inside the callback we check the response data to see if it contains 1. This will be sent back by our AJAX function we will create later, if it is 1 we take it as meaning true & show an options saved box, if it is anything else we show an options not saved box. The message boxes are simple jQuery that show a message in styling defined by WordPress & then use a simple setTimeout & clearTimeout to show & hide the boxes. I’m not going to add to the length of this tutorial by explaining them, if you want to know more about them leave a comment & I’ll explain more about the functions. We finally use return false in the submit event to stop the form from submitting and refreshing the page.

Creating The HTML Form

Next we are going to create the form needed for the data to be inserted by the user. My form isn’t pretty & does absolutely nothing, by that I mean although it saves data the data isn’t used in any way. Here is my code, remember that this function is used by the add_theme_page function we called earlier:

The is the function that creates the page you see when you visit the admin page. Although you can use the header section to add your own CSS code I have just used the default WordPress CSS. That is why the HTML starts with a div with the class of wrap.

The form is the important part. You must give it a name, and the ID must be the same as the one you used in the jQuery submit event function earlier. The interior of the form can include anything your theme requires, however you need 2 extra input fields. These fields are hidden ones that send required data for the AJAX to work correctly. First is the action hidden field, the value should be whatever you want WordPress to call it’s hook that will be used to hook the function we will make to get results from the AJAX call. The other hidden field security is the infamous nonce code used by WordPress for security. The value must be as shown however you can change the word inside wp_create_nonce() to anything you like (preferable something relevent to your theme), remember it though as we’ll need it later.

We have also added in some PHP to recall the options saved in the database. We simply store the options into a variable & then echo out the data into the value fields. In the case of checkboxes we check for the value on & the add ‘checked’ if it is detected. I’ve used a ternary as it is shorter when writing PHP inline with HTML.

Creating The PHP AJAX Function

Ok so we are nearly done. We just have to create the function called by jQuery, so here’s what I ended up with:

First is add_action the name of this hook was determined by the value of our action field in our form, you just prepend wp_ajax_ to the front of it. The function can be called anything you like again, but try to keep them all relevent to your theme.

Now onto the actual function. First we use a function defined by WordPress to check if the nonce key we received is active & valid. This is where you need to recall that string I told you to remember as it has to be written in the first parameter identically to the one you wrote in wp_create_nonce(). If like me you haven’t used the default post value $_POST['_ajax_nonce'] you will need to tell the function what the $_POST key for the nonce code is, in our case security is the code. This is gotten from the name parameter of our hidden form field. Next we transfer our data from the $_POST global array to a variable called $data, we unset both the nonce key & our action which are passed by the form & are no longer needed. One thing to note is that if check_ajax_referer() does not validate the code it will die outputting ‘-1′, so when debuging if you receive that value you know what is doing it.

To stop our next piece of code throwing an error we need to get the options stored in the database & if they are empty create a blank array on the variable that would normally hold them. get_option() asks WordPress to go to the database and get the data in the wp_options table with the key provided. In our case that is test_theme. All we do is check if the returned value is an array. If it is we grab the data. If not we set a blank array.

Next it gets a little strange. I don’t know if it is a bug or not, but if the values sent from the form are the same as the current database values update_option() will return as if it failed, so we need to screen the options first. We check to see if the options in the database are the same as the once recieved from the form submission by checking for differences using array_diff(). To get the differences correctly we check both arrays against each other & then merge the results together. We also set a blank array if there is no data sent to trigger our jQuery error. If $diff is not an empty array we have differences and can safely save the options. If the update is successful stop PHP processing & echo out 1 to our jQuery function. If it fails then stop processing & echo 0 to our jQuery function. Else if the variable $diff is empty we do not need to update the database since the options are identical so just stop processing & echo out 1.

A quick note about update_option(). You can change the part in the parentheses to anything you like, but try to make it unique & relevent to your theme in some way. Also you may wonder how it is storing an array in a single database field, this is because update_option() auto serializes an array before saving it. In the same vein, get_option() unserializes a serialized array back into a normal array when it grabs data. These are important things to remember when using both these functions.

We’ll that is it, I think. I don’t think I’ve missed anything. I’ve been at this post so long I’ve lost feeling in my legs. :lol: I hope this post helps you, despite it ending up a lot more complicated that I’d wanted it to. You may need to read the post a few times to get a proper understanding of what is going on. If you have any problems or notice something I’ve missed please, please, please email me or leave me a comment & I’ll sort it out as quickly as I can.

Thank you for reading, good luck, and I hope I haven’t made your brain explode. ;)

written by

WordPress wizard, coding ninja and all round cool guy. Loves Sci-Fi, geeky stuff, and of course Firefly. Currently a self confessed addict of Korean & Japanese Pop.



Author’s gravatar

Hi Kegan,

To coin a phrase from a famous advert. It does exactly what it says on the tin. It grabs the data held in the option named test_theme from the WordPress options table.

Author’s gravatar

but where is the data in

coming from?… i don’t see it anywhere else, which is why I’m confused

Author’s gravatar

It is where all the form data, sent from the form, is saved. You can see that it saves it on line 25 of the last block of code. The key is update_option('test_theme', $data). That tells WordPress to save all of the data inside the $data variable into the WordPress options table. If $data is an array it is auto serialized for us.

Author’s gravatar

I pretty much pasted the Javascript and AJAX PHP, but it keeps refreshing! And it doesn’t even save the data. What could I possibly be doing wrong?

Author’s gravatar

Yes, I fixed it! The form was being added dynamically, so I had to change the .submit for a .on event. Also, I had to do a little change so checkboxes work :P
Awesome info, thanks a lot!

Author’s gravatar

For check-box just add value=”on” in the input field. Everything else works fine. Thanks for the code.

Author’s gravatar

Ahh, I’m an idiot, I hadn’t realized that it wasn’t in the code. It looks like I’ve accidentally removed it when I was copying the code into the post.

Will add it back in so others aren’t confused. Thanks for the nudge.

Author’s gravatar


Nice tut!
How can I multiply inputs with name=”test_text” from the form using ajax? I mean for default I have a form with only one text input, but with ajax to can add more. Do you know how?


Author’s gravatar


Adding more text inputs should be possible. It’s not so much AJAX as DOM manipulation. I can’t show you how to do it in your specific situation, but in general you’d use:

That should add your field to your form.

Author’s gravatar

nice tutorial

can you give me your email for asking.


Author’s gravatar

Hey thanks… is it possible to add this functionality to a wordpress plugin in the frontend?


Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">