How to Load WordPress Post With AJAX

We are running a YouTube Channel where we share technology-based videos regularly. Recently, our one of subscriber asked us how to load WordPress post with AJAX. In reply to him, we decided to write a post on his question. So in this article, we study how to load WordPress post with AJAX using a load more button and using page scroll.

The difference between the load more and a page scroll is quite simple. When using load more button, you need to click on a button to see the next set of articles. And on page scroll, when you scroll to end of a viewport, next set of articles will automatically get loaded.

Let’s assume you have a couple of posts and you need to display 2 posts first-time on page load and then by clicking on ‘Load More’ or on ‘Page Scroll’ next 2 posts should display. This process would continue until all of your articles are displayed.

Create a new page called ‘Blog’. To display your posts on Blog page create custom template page-blog.php in your active theme directory.

Now when users visit your blog page they should see 2 posts. So, add the code below in your custom template file.

<div class="entry-content">
	<?php 
	$args = array(
		'post_type' => 'post',
		'post_status' => 'publish',
		'posts_per_page' => '2',
		'paged' => 1,
	);
	$my_posts = new WP_Query( $args );
	if ( $my_posts->have_posts() ) : 
	?>
		<div class="my-posts">
			<?php while ( $my_posts->have_posts() ) : $my_posts->the_post(); ?>
				<h2><?php the_title(); ?></h2>
				<?php the_excerpt(); ?>
			<?php endwhile; ?>
		</div>
	<?php endif; ?>
	<div class="loadmore">Load More...</div>
</div>

Here, we used ‘paged’ key and pass the value ‘1’ to it. ‘paged’ is a key used in WordPress when it comes to pagination. ‘paged’ => 1 means first page.

You would notice div block with the class ‘loadmore’. On clicking on Load More, we will use our magic.

Load WordPress Post With Ajax On Load More Button

We first write a little bit of jQuery and give a call to the AJAX function which in return will give us our next posts.

<script type="text/javascript">
var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
var page = 2;
jQuery(function($) {
	$('body').on('click', '.loadmore', function() {
		var data = {
			'action': 'load_posts_by_ajax',
			'page': page,
			'security': '<?php echo wp_create_nonce("load_more_posts"); ?>'
		};

		$.post(ajaxurl, data, function(response) {
			if(response != '') {
                $('.my-posts').append(response);
                page++;
            } else {
                $('.loadmore').hide();
            }
		});
	});
});
</script>

What we are doing here is, take a javascript variable ‘page’ with initial value 2 as we are going to start with second-page pagination and increment the variable after each success call. Also, after each response, we are appending it to our posts listing.

We pass the action parameter ‘load_posts_by_ajax’ to ajax call so it is needed to handle this AJAX action. Open your functions.php file and add the below code at the end of a file.

add_action('wp_ajax_load_posts_by_ajax', 'load_posts_by_ajax_callback');
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_posts_by_ajax_callback');

In above WordPress actions, we call the callback function load_posts_by_ajax_callback which we are going to define in the next step. You can define this function in your functions.php.

function load_posts_by_ajax_callback() {
	check_ajax_referer('load_more_posts', 'security');
	$paged = $_POST['page'];
	$args = array(
		'post_type' => 'post',
		'post_status' => 'publish',
		'posts_per_page' => '2',
		'paged' => $paged,
	);
	$my_posts = new WP_Query( $args );
	if ( $my_posts->have_posts() ) :
		?>
		<?php while ( $my_posts->have_posts() ) : $my_posts->the_post(); ?>
			<h2><?php the_title(); ?></h2>
			<?php the_excerpt(); ?>
		<?php endwhile; ?>
		<?php
	endif;

	wp_die();
}

Now you should see the ‘Load More’ button in action and should load the WordPress post through Ajax.

Load WordPress Post With Ajax On Page Scroll

Some users don’t want a load more button to display the next posts. Instead, they prefer the next posts should display once the user reaches the end of a page. To achieve this, We just need to write logic which captures the event at the end of a page, a rest of the code is the same as the ‘Load More’ button. Below is the jQuery code for page scroll.

$(window).scroll(function() {
	if ($(window).scrollTop() == $(document).height() - $(window).height()) {
		var data = {
			'action': 'load_posts_by_ajax',
			'page': page,
			'security': '<?php echo wp_create_nonce("load_more_posts"); ?>'
		};

		$.post(ajaxurl, data, function(response) {
			if(response != '') {
                $('.my-posts').append(response);
                page++;
            } else {
                $('.loadmore').hide();
            }
		});
	}
});

The above method used the ‘paged’ value passed to it and fetch the next 2 posts of the next page. This response we are returning to our jQuery code which will handle remaining magic.

That’s it! Please go ahead and try this technique. For any questions and suggestions please share comments below.

Related Articles

If you liked this article, then please subscribe to our Youtube Channel for video tutorials.

76 thoughts on “How to Load WordPress Post With AJAX

  1. Perfect tutorial! One question, how do I hide the Load more button when it’s reached the max number of posts? Thanks

      1. Thanks for replying. I changed my script to the following.

        It shows the button and loads more on click as it should do.
        But it still shows when there is no more to load, It only hides when I click the button again.
        Your help is much appreciated.

        $.post(ajaxurl, data, function(response) {
        if(response != ”) {
        $(‘.my-posts’).append(response);
        page++;
        } else {
        $(‘.load-more’).hide();
        }
        });

      2. Here is my full script:

        $(‘body’).on(‘click’, ‘.loadmore’, function() {
        var data = {
        ‘action’: ‘load_posts_by_ajax’,
        ‘page’: page,
        ‘security’: ”
        };

        $.post(ajaxurl, data, function(response) {
        if(response != ”) {
        $(‘.my-posts’).append(response);
        page++;
        } else {
        $(‘.loadmore’).hide();
        }
        });
        });

  2. I have got the basic version working, but how do I adapt it for my needs… ?

    – I have a custom query – how do I accommodate this? Actually, multiple similar query blocks on the same taxonomy template, each output with foreach, and each of which has slightly different arguments. One problem with the code as-is is that it does not discriminate. How can I made the call specific to the section in which it was clicked and to use the same query?
    – Also, when I click “Load more”, *all* sections load new posts. But it should only be the section which was clicked.
    – I could adapt the .my-posts class in the HTML to something like .my-posts-somethingunique – but how can I make the Javascript service anything more than .my-posts, and how can I ensure that load comes from the correct “Load more” link click? Something to do with a data= parameter in the tag… ?

    More about my case at https://wordpress.stackexchange.com/questions/328685/how-to-load-more-posts-via-ajax from before I got this basic version working.

    Thanks.

  3. Hi Sir,
    Implemented the steps you mentioned, but i have showing :-
    wp-admin/admin-ajax.php 500 (Internal Server Error)
    I had installed Ajax Load More plugin.. but now i removed it , also i increased the memmory limit in wp-config.php

  4. Hi, I find a solution for loadmore button. It will be hidden if no more post.
    var data = {
    ‘action’: ‘load_posts_by_ajax’,
    ‘page’: page,
    ‘security’: ‘@php echo wp_create_nonce(“load_more_posts”); @endphp’,
    ‘max_page’: ‘@php echo $posts->max_num_pages + 1; @endphp’
    };
    if(response != ”) {
    $(‘.post-boxs’).append(response);
    page++;
    }

    if (page == data[‘max_page’]) {
    $(‘.load-more’).hide();
    }

  5. Thank you for the code but I have problems with metabox data in my-posts div wrapper.

    For some reason the_content() or the_title() works well but for example values like $dayevent = get_post_meta( $post->ID, ‘dayevent’, true ); no.
    Any help appreciated.

  6. Hi !
    Great article !
    But i had a problem with posts_per_page
    If i set defaulft show post are 9 post, then click load more 3 post but it not work.
    What happen with that? and how can i fix them?
    Need your help ! Thanks. 🙁

  7. Hi! in the loop of repeated entries, tell me how to remove? $my_posts = new WP_Query( $args );
    if ( $my_posts->have_posts() ) :
    ?>
    have_posts() ) : $my_posts->the_post() ?>

  8. 1. How can I use load more button for custom posts type taxonomy term like category. I use filtering option of custom post category
    2. How can I remove load more button when all of my posts are loaded. Please send coding script of above query.

    1. When I click load more button always show 0.every click a 0 is added. How can i remove or hide this 0 value. Please give me a suggestion.

  9. Hi Its a nice article, which helps me to achieve something I wanted very long time. Even non coder can learn this and try this out.

    Here is my request:
    Can you add Lazy load image before loading posts and hide after loaded. Also is the any chance we can add the fadeIn effect to the posts when they added?

  10. How can we add select dropdown to select categories and load posts from that category ?
    Im trying to add this functionality here in this code

  11. With this idea the button is not hide automatically. Here user must be click on Button, then after if There is no posts then button will be hide.
    if(response != ”) {
    $(‘.my-posts’).append(response);
    page++;
    } else {
    $(‘.load-more’).hide();
    }

    But i want that without clicking the button at last, the button should automatically hide, if there is no posts.
    How to do that? any idea?

      1. $.post(ajaxurl, data, function(response) {
        console.log(response);
        if(response == ”){
        $(‘.loadmore’).hide();
        }
        $(‘.jmasonry’).append(response);
        page++;
        });

  12. Hello, I think it is working but with some caveats…. The initial button doesn’t get hided after click and the button doesn’t move, meaning it should be at the end of the loaded posts… oddly if there are no more posts and the actual already used button gets clicked it populates duplicated entries Mmm. Any fix?

    1. We have written $(‘.my-posts’).append(response); And our Load More button is outside of div with class my-posts. So Load More will always stick at the end. And after each response, we are incrementing page variable so there is no chance of duplicate records. Maybe in your case you are missing the position of Load More.

      1. Oh you are right I fixed that it is working ok 😉
        What do you recomend for hiding the load more button when there are no more posts to display and after clicking the load more button?
        For the second maybe I should mix the following code:

        $(function(){
        $(“.loadmore”).on(‘click’,function() {
        $(this).css(‘visibility’,’hidden’);
        });
        });

        with the code in the guide:

        var ajaxurl = “”;
        var page = 2;
        jQuery(function($) {
        $(‘body’).on(‘click’, ‘.loadmore’, function() {
        var data = {
        ‘action’: ‘load_posts_by_ajax’,
        ‘page’: page,
        ‘security’: ”
        };

        $.post(ajaxurl, data, function(response) {
        $(‘.my-posts’).append(response);
        page++;
        });
        });
        });

        1. You should manage it from ajax callback functions. Check where WP_Query returns records. If not send flag(like noresult) in response else send next posts(which we are currently returning).
          And then in JavaScript, you can hide the Load more on the basis of a flag.

          1. Ok really wish I knew that much enough to follow that instructions, for which I’m afraid I don’t. If you guide me (like pointing me to the reference) I will read it/learn and try it out. Regards.

          2. When no posts are available we get empty ajax response which you can use to hide load more button. In the JavaScript code of ajax response change the code like
            if(response != ”) {
            $(‘.my-posts’).append(response);
            page++;
            } else {
            $(‘.load-more’).hide();
            }

          3. Ok edited the code as follows:

            var ajaxurl = “”;
            var page = 2;
            jQuery(function($) {
            $(‘body’).on(‘click’, ‘.loadmore’, function() {
            var data = {
            ‘action’: ‘load_posts_by_ajax’,
            ‘page’: page,
            ‘security’: ”

            };

            $.post(ajaxurl, data, function(response) {
            if(response != ”) {
            $(‘.my-posts’).append(response);
            page++;
            } else {
            $(‘.load-more’).hide();
            }
            });
            });
            });

            But the button is not loading more posts.. will keep trying changes..

  13. Hi,
    I’m using this script in my blog section button click is working but i am going to implement window scroll is not firing please advise to me.

  14. Hi Artisan,

    Now I’m wondering something else. I would like for the button to dissapear when all posts are loaded, it that possible?

    Thank you!

    1. Yes, it is possible. Wrap your each post in a div with the common class.
      By this way, calling ‘length’ method we come to know the count of post divs.
      On the top of a front page PHP file, fetch the count of all posts and assign it to a variable.
      Assign this PHP variable to JavaScript variable. Now on each Ajax response check if a count of post divs reaches a value of a variable. If both values are same then hide load more button.
      Let me know if you understand this or need more help.

      1. Hi,
        I’m also interested n this, but i’m lost on details, can you help me with hiding load more button at the end of posts ?

        Thanks

        1. I’ve solved this by adding “else” to the loop to creating a new “div” that will show a message if no more posts. After Edit this:

          No More Posts!
          0 ) $(‘.loadmore’).hide();

    1. “I had the same .class on my div in my first query as in my second query!” Hello Victor! Can you share the steps on how you did it?

    2. Yes got it working as well… in case someone wonders how:
      Rename all “my-posts” for the second instance of ajax for something like “my-posts2”, same with “security2”, “loadmore2”,
      wp_ajax_load_posts_by_ajax2′, ‘load_posts_by_ajax_callback2’);
      add_action(‘wp_ajax_nopriv_load_posts_by_ajax2’, ‘load_posts_by_ajax_callback2, ‘load_posts_by_ajax2, “load_more_posts2”, “.my-posts2” Hope it helps…

      1. Forgot to add you may need to create a second instance of the code for each ajax instance. For example for three ajax buttons you should have:
        For the first ajax button:

        var ajaxurl = “”;
        var page = 2;
        jQuery(function($) {
        $(‘body’).on(‘click’, ‘.loadmore’, function() {
        var data = {
        ‘action’: ‘load_posts_by_ajax’,
        ‘page’: page,
        ‘security’: ”

        };

        $.post(ajaxurl, data, function(response) {
        $(‘.my-posts’).append(response);
        page++;
        });
        });
        });

        For the second ajax button:

        var ajaxurl = “”;
        var page = 2;
        jQuery(function($) {
        $(‘body’).on(‘click’, ‘.loadmore2’, function() {
        var data = {
        ‘action’: ‘load_posts_by_ajax2’,
        ‘page’: page,
        ‘security2’: ”

        };

        $.post(ajaxurl, data, function(response) {
        $(‘.my-posts2’).append(response);
        page++;
        });
        });
        });

        For the third ajax button:

        var ajaxurl = “”;
        var page = 2;
        jQuery(function($) {
        $(‘body’).on(‘click’, ‘.loadmore3’, function() {
        var data = {
        ‘action’: ‘load_posts_by_ajax3’,
        ‘page’: page,
        ‘security3’: ”

        };

        $.post(ajaxurl, data, function(response) {
        $(‘.my-posts3’).append(response);
        page++;
        });
        });
        });

        Maybe this could be done in a more efficient way.. but thats at least should work

        1. I realized there’s a problem with using in the same page two ajax buttons… they share the page, so that if for example I use the first button once and ten use the other button, the later will load not the second page but the third… Haven’t figured out yet how to solve it… must be something like assigning a different name for each page?

          1. So far the second button looks like this:

            1. in header:
            var page1 = 2;
            ‘page1’: page1,

            2. in functions.php
            $paged1 = $_POST[‘page1’];
            ‘paged1’ => $paged1,

            3. in the template
            $paged1 = ( get_query_var( ‘paged1’ ) );
            ‘paged1’ => 1,

          2. Use 3 different pages variables for each ajax call so it does not get repeated for each other.
            var page1 = 2;var page2 = 2;var page3 = 2;

          3. @Sajid Can you elaborate more because I don’t think you mean the above… like dummy proof it may serve others as well

          4. I got it, the values that have to be modified are (I added an extra “7”):
            in footer or header
            var page7
            ‘page7’: page7,
            page7++;
            in functions
            $paged7 = $_POST[‘page7’];
            ‘paged’ => $paged7,

  15. Hi Artisan,

    I’ve implemented your code and it works great when the query is on a page with no other queries. However, I would like to implement it on my front page. On that page I have two other queries. When i press the Load More-button, the ajax-function loads the correct posts but it loads the posts twice.

    I’ve tried to use the wp_post_reset but it doesn’t work.
    Have you noticed this before?

  16. John, It is possible to apply load more post of different categories multiple times. In you case need to work on some logic to achieve the final goal.

  17. Great bro !

    What if: Let`s assume, I do have posts slider on my page, then I want to display the content of a post that I clicked, but I want it to be shown below the post slider.

Leave a Reply

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