Tutorials UPDATED: 02 May 2023

Ajax and WordPress

Tassos Antoniou

7 min read

The Ajax technique, as we explained in our introductory article on Ajax has become popular as it allows us to update a part of the webpage content without having to refresh the page. This makes for an improved user experience.

WordPress sites are of course no exception. How we use Ajax in WordPress however differs compared to use on other web applications.

What is admin-ajax and How does it Work?

WordPress has already implemented Ajax for its own admin features, such as auto-saving, instant updates, comment moderation, adding/deleting posts etc. This means that it is ready for us to use by just utilizing the related functions provided by WordPress.

The key file for this purpose is the admin-ajax.php file, located under the wp-admin folder, which is used for creating a connection between the client and the server.

Inside this file, around line 159, you can see how all Ajax requests are registered by some action hooks.

if ( ! empty( $_GET['action'] ) && in_array( $_GET['action'], $core_actions_get, true ) ) {
	add_action( 'wp_ajax_' . $_GET['action'], 'wp_ajax_' . str_replace( '-', '_', $_GET['action'] ), 1 );

if ( ! empty( $_POST['action'] ) && in_array( $_POST['action'], $core_actions_post, true ) ) {
	add_action( 'wp_ajax_' . $_POST['action'], 'wp_ajax_' . str_replace( '-', '_', $_POST['action'] ), 1 );

The wp_ajax_{$action} refers to the logged in users and the wp_ajax_nopriv_{$_REQUEST[‘action’]} to the site visitors. If you want to create a request that includes all users, we will have to use both hooks.

So with the help of these actions, you can hook a custom function and pass your data to WordPress to make an Ajax request. Let’s take a look at this in action.

WordPress Ajax Example

We will use the same example as we did in our Ajax introductory article and create a form that allows the user to search in the articles’ titles and see the suggested results on the fly.

In our theme’s header space, we will insert the HTML output for our search form. We use the Twenty Twenty-One theme so we edited the header.php file located under the theme’s main folder and inserted the following lines before the <div id=”content” class=”site-content”> line.

<p><b>Search in articles:</b></p>
        <input type="text" class="userInput">
<p>Articles available: <span class="txtHint"></span></p>

Now the form that the user can use should be visible in the front end.

NOTE: Here, we will directly edit the theme’s header.php file without creating a child theme. This is not good practice and has a number of drawbacks. If you want to learn more for the importance of child themes, please read our related article. For the purposes of this example we have kept the code simple and on topic. As such it’s not suggested you use this code in a production website.

Try our Award-Winning WordPress Hosting today!

Next thing is to include the JavaScript function that will send the request. We will use jQuery instead, since it already comes with WordPress and is ready to use. Of course, we have to include a script the WordPress way.

Enqueue Our Script

We will tell WordPress about the JS file’s existence, by editing the theme’s function.php file and enqueue the script like this. Our file will be the custom.js which we have created and put inside a new “js” folder under the theme’s main folder.

function ajax_search_script() {
    wp_register_script( 'custom-script', get_stylesheet_directory_uri(). '/js/custom.js', array('jquery'), false, true );
    $script_data_array = array(
        'url' => admin_url( 'admin-ajax.php' ),
        'nonce' => wp_create_nonce( 'search_titles_nonce' ),
    wp_localize_script( 'custom-script', 'ajax_object', $script_data_array );
    wp_enqueue_script( 'custom-script' );
add_action( 'wp_enqueue_scripts', 'ajax_search_script' );

In the ajax_search_script() function, we registered and localized the script, and then enqueued the localized data with the built-in wp_enqueue_script() function. Then we hooked the ajax_search_script() function on the wp_enqueue_scripts, which is the proper action to use when enqueuing scripts in WordPress.

The use of wp_localize_script might be confusing here because, as a WordPress function, it was originally designed for translating any strings used in your script. However it is also frequently used to pass generic data from PHP to JavaScript. In our case, to pass the Ajax URL and nonce object.

The nonce use is necessary so that the jQuery Ajax request can be validated as a request that is coming from the website. If you are not familiar with the use of nonces in WordPress you can read more in our related article.

The ajax_object is the value of the required $object_name parameter of the wp_localize_script() function and is what will later be used in the jQuery code.

Great! Now let’s fill in our function with the right content.


Inside the custom.js file we included our jQuery.

jQuery(function($) {
    $('.userInput').on('keyup', function() {
        var input = $(this).val();
        if(input != '') {
            var data = {
                'action': 'get_articles_titles',
                'search_text': input,
                'nonce': ajax_object.nonce
            $.post(ajax_object.url, data, function(response) {


This time we used jQuery and JSON in order to pass the desired data, action, search_text, nonce, to the server side script. The callback get_articles_titles() function, will be responsible for processing the data in the back end, preparing the results and sending back a response.

Also, as you can see, we use the ajax_object from wp_localize_script with its two array values, nonce and url.

The Hooks

Now we have to bind the authenticated Ajax actions with the necessary hooks we mentioned previously. We remind you that in order to include both logged and non-logged users, you have to use both hooks. In your functions.php file add these two lines under the code added before for enqueuing the script.

add_action('wp_ajax_get_articles_titles', 'get_articles_titles');
add_action('wp_ajax_nopriv_get_articles_titles', 'get_articles_titles');

As you may have already noticed, the hook name is actually a prefix followed by our action name. The get_articles_titles hooked function is where we will actually retrieve the articles’ titles. We will define this function inside functions.php as well.

function get_articles_titles() {

    check_ajax_referer('ajax_nonce', 'nonce');
    $input = $_POST['search_text'];
    $args = array(
        'posts_per_page'   => -1,
        'post_type'        => 'post',
    $the_query = new WP_Query( $args );

    $autocomplete = "<br>";
    if ( $the_query->have_posts() ) {
        while ( $the_query->have_posts() ) {
            $title = get_the_title( get_the_ID() );
            if ( strpos( strtolower($title), strtolower($input) ) !== false ) {
                $autocomplete .= $title . "<br>" ;
    echo $autocomplete;

The check_ajax_referer is responsible for verifying that the Ajax request is not processed externally. 

The necessary parameters here are the action, which is related to the 'nonce' => wp_create_nonce( 'ajax_nonce' ) inside your ajax_search_script() function, along with the value related to nonce.

And that’s it! We just created a very simple Ajax-PHP example. At this point, if you try the code in a test WordPress environment, it should be working like this.

Where the Service 1-5 are the titles of our test posts.


This was an article on how we can increase responsiveness and performance on a WordPress website by taking advantage of the Ajax benefits. Hopefully, you are ready now to use similar techniques on your own website and enjoy improving the user experience!

Start Your 14 Day Free Trial

Try our award winning WordPress Hosting!


See how Pressidium can help you scale
your business with ease.