Create ONE callback for all page templates, post filter queries + paginated pages, triggering pagination via AJAX

Because of this line:

$paged = get_query_var( "paged" ) ? get_query_var( "paged" ) : 1;

This is inside a function that is used on both an AJAX handler, and on a page request. get_query_var pulls the parameters from the main query ( aka the primary WP_Query that powers functions such as the_post, have_posts() etc ). But this will never work in an AJAX request.

For this reason, when you request the next page from AJAX it will always result in page 1. If you want something other than page 1 then you need to include the number of the page you want in the javascript that sends the AJAX request, pass it along, then read it and put it in the WP_Query parameters directly. Even if there was a main query it would not be the same main query.

Remember, every request to the server loads WordPress from a blank slate, AJAX request handlers share nothing with the page that your browser has open unless you explicitly send them the data you want to share along with the request as POST/GET variables. There is no shared pagination state behind the scenes or magic that glues it together.

Additionally, because you included the pagination HTML in the AJAX response you’ll now have a next page link that leads to page 2, but triggers AJAX that loads page 1 ( why would it know to load page 2? get_query_var won’t work, there is no main query to get a query var from! ).


What’s more, I have a strong suspicion that you’re either unaware of archive-mycustompost.php, the pre_get_posts filter, or the ability to change the URL of the CPT archive when registering the CPT, or that query parameters for the main query come from the URL and you can add extra parameters e.g. example.com/?s=test&posts_per_page=7&paged=2 gets the second page of a search query for “Test” that has 7 posts per page. In the majority of cases a secondary query and a custom page template are completely unnecessary.