I have a simple WP post query, which is supposed to load 8 posts per page, with a post navigation displayed below, like so:

$query_args = [
  "post_type" => "post",
  "post_status" => "publish",
  "posts_per_page" => 8,
  "paged" => ( get_query_var( "paged" ) ? get_query_var( "paged" ) : 1 )

// Get all the posts
$posts = new \WP_Query( $query_args );

$output = "";

if ( $posts->have_posts() ) {

  while ( $posts->have_posts() ) {

    $output .= get_the_excerpt();


  $output .= "<div id=\"post-navigation-links\">".

  paginate_links( array(
    'base' => get_pagenum_link(1) . '%_%',
    'format' => '/page/%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $posts->max_num_pages
  ) ).


} else {

  $output = '<div id="no-posts-found">Nothing found</div>';

} // loop which is entered if no posts matching the query args have been found


This all works when I load the page.

On that same page, I have a search field. If I submit that search field, I call exactly the same code as the one on page load via AJAX (code above) to replace the page content with the new result, just with the difference of the additionall "s" parameter in the $query_args. Result of this: I get exactly the matching posts, with a proper pagination displayed below. When I however click on the pagination links on the updated page, I get a 400 Bad Request and a 0 answer from the server (page all white and only containing a 0). On the initial page load, pagination works perfectly.

When comparing the URLs after clicking on a page load:

Before content being replaced with string query (on page load), the pagination URLs have this structure and work perfectly:


After content being replaced with string query, the pagination URLs have this structure and result in 400 errors:


So the problem seems to occur at the ajax handler. Any idea???

  • How did you make the AJAX request? Can you edit the question and add your JS code - and if it's okay, share a screenshot of the AJAX/XHR request (in Chrome, open the browser dev tools and check the Network tab)? But I'm guessing your request did not send the required action parameter.
    – Sally CJ
    May 12, 2021 at 11:15
  • The AJAX request used to filter the posts by a search string works perfectly, that's not the problem, so there's no use in checking on that; but I may wasn't clear in my question. I've first also thought that there must be an action / nonce problem, but it's the request that I don't touch which has problems; so I cannot say why that happens.. I'll elucidate the problem in my answer below, as I found a solution, but did not really understand this problem...
    – DevelJoe
    May 12, 2021 at 13:09
  • works perfectly = I pass one single parameter; the typed search string, to the request, and retrieve it to use it in PHP as shown in the code of my question for the "s" parameter, and I get a perfect 200 response back with the updated content, updated pagination links as explained, and no server / js errors reported, and the filtering of the posts is also correct.. The problem happens only after trying to use the pagination generated in this way; see my answer below..
    – DevelJoe
    May 12, 2021 at 13:36
  • So I only had a quick glance at your answer, but I'll check it thoroughly soon.. And actually, if you shared your JS code and more of your code than what's currently in the question, I (or someone else) could at least provide suggestions on preventing the issue from happening, specially if we could test your code and try to reproduce the issue.
    – Sally CJ
    May 12, 2021 at 17:50

1 Answer 1


I seemingly found a solution, and this is a lot more complicated than I thought. So to be clear again, let's say I have a page like this:

  <!-- Posts from query (see question) inserted here -->
  <!-- Pagination Links from query (see question) inserted here -->

To generate the <main> part, I use a function which holds the code of my question, let's say function A, which returns the content to be inserted into <main> as HTML string. So on page load, I simply insert the returned value of function A into the <main> part.

THEN, I have a button on my page which re-calls function A via wp - ajax, and replaces the content of <main> with the exact same value, by additionally using the s parameter in the WP_Query as described in my question.

The content gets updated successfully, as well as the pagination links do, with one difference: wp-admin/admin-ajax.php?ranum=0.825265473159516 gets added into the URL of each pagination link, the random number probably to avoid cached subpage results. When clicking on one of these pagination links, I get a 400 error, with no request / response data, and a blank page with a 0 appearing as the result. Nothing else useful shown in the network analysis.

I then came across this post. This tells how to add the search string parameter to the URL to be able to use it throughout the updated pagination. I did this, and then edited the search.php template page in the theme to have the same content as the concerned page, by using the $_GET["s"] parameter for function A called in search.php, and it now all worked. The changed code in function A is:

$paginate_args = [
  'base' => home_url( '/%_%' ),
  'format' => 'page/%#%/',
  'current' => max( 1, get_query_var('paged') ),
  'total' => $posts->max_num_pages

// $query_string holds the sanitized input of the typed string 
// into the search field

if( $query_string !== "" ) {

  $paginate_args['add_args'] = array( 's' => $query_string );


$output .= "<div id=\"post-navigation-links\">".

        paginate_links( $paginate_args ).


The pagination of the updated page containing search-filtered posts now perfectly works. Interestingly, the link's structure is now:


so the wp-admin/admin-ajax.php part is gone from the link, but we are also loading a different page now (the search page), and not simply making an AJAX request. So this works now, but I have no clue how / if you can make this behaviour work with an AJAX request, and still don't know what the actual problem was. Of course, it would still be better to find an AJAX solution, to avoid to need to reload the entire page with each pagination, but this even seems to be default behaviour in wp pagination. Maybe you're better off developing your own pagination scripts, which sets a specific offset and post limit of 8 to each pagination request, or similar..

The problem was may related to the fact that I previously used get_pagenum_link(1) as the base URL for pagination, which is why when called via AJAX, the pagination links hold the AJAX URL part.. Still, when only switching that part with the new home_url( '/%_%' ), when you click on one of the new pagination links, you get to the corresponding page of the initial pagination, loaded on page load; so the only solution seems to be the one I've specified in this answer (page re-loads + search page) or custom AJAX scripting, as mentioned.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.