How to Load WordPress Post With AJAX

I am running a YouTube Channel where i share technology based videos regularly. Recently, my one of subscriber asked me how to load WordPress post with AJAX. In this article, we study how to load WordPress post with AJAX using a load more button and using page scroll.

Let’s assume I have a couple of posts and I need to display 2 posts on first-time 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 my all articles are displayed.

I have created ‘Blog’ page. To display posts on Blog page I created custom template page-blog.php and kept it in my theme directory.

When users visit my blog page they should see 2 posts. So, I added below code in my template.

<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, I use ‘paged’ key and pass the value ‘1’ to it. ‘paged’ is fix 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 of Load More, we will use our magic.

Load WordPress Post With Ajax On Load More Button

We first write little bit 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) {
			$('.my-posts').append(response);
			page++;
		});
	});
});
</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.

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 declare in the next step. You can declare 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();
}

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 next posts should display once the user reaches end of the page. To achieve this, We just need to write logic which captures the event for the end of a page, rest of the code is same like ‘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) {
				$('.my-posts').append(response);
				page++;
			});
		}
	});

Above method use the paged value passed to it and fetch the next 2 posts of the respected 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.

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

39 thoughts on “How to Load WordPress Post With AJAX

  1. 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.

  2. 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.

  3. 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?

    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,

  4. 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();

  5. 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.

  6. 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..

  7. 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?

Leave a Reply

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