I have a custom page template, I'm using a standard WPQuery to fetch the posts from the default posts custom post type. I'm looping through all the posts however now I have more posts than I allow in the settings of the admin. Instead of changing the limit I want to use some standard WP pagination. However, none of the functions work on a custom page template but do when used on index.php.

<?php /* Template Name: News page */
get_header(); ?>
<?php $args = array(
    'post_type'  => array( 'post' ),

  // The Query
  $query = new WP_Query( $args ); ?>

<div id="primary" class="content-area">
  <main id="main" class="site-main full-width pd" role="main">
    <div class="news-loop">
        <div class="row">
          <?php if($query->have_posts()) :
            while($query->have_posts()) :
              <div class="col col-md-4">
                <a href="<?php the_permalink(); ?>">
                    <div class="cut-box">
                        <?php the_post_thumbnail( 'gallery' ); ?>
                <span class="date">
                    <?php echo get_the_date('d/m/Y'); ?>
                <h3><?php the_title(); ?></h3>
                <?php the_excerpt(); ?>
                <a href="<?php the_permalink(); ?>">Read More...</a>
            <?php endwhile; ?>
            <p class="nav"><?php previous_posts_link(); ?></p>
          <?php endif; ?>
          <?php wp_reset_query(); ?>
<?php get_footer(); ?>

I've used the previous_posts_link() function as a test but nothing is returned in the dom.

Is it possible to use standard wp pagination on custom page templates?


2 Answers 2


You can't.

wordpress pagination API is designed to work with the main query and not with a secondary one as in your case.

There are many answers to similar questions around here with a all kinds of hacks to go around it, and while applying enough hacks, might make it work for your specific case, the basic answer should be that if you need pagination on a secondary loop, you have to write it yourself.

What you should do is to create a main query for the URL in which you want the page to be. Set your own rewrite rule to parse the specific url into whatever wp_query arguments you need for the loop, and use the template_redirect hook to use your specific template for that URL.

You can still use a page as a sort of "configuration scree" for the title and whatever other attributes you will need for that template to generate the proper HTML.

While in this solution you need to set the details correctly in several ways, it is IMO a much more reliable solution than trying to hack the pagination APIs.

  • wp_paginate_links() allow create pagination for a custom page and custom queries. And paginate links dont use secondary loop. Just parse parametr page/2` as 'paged' => 2. And create custom pagination is not hack or something wrong. You put in url self parametr and then parse him into paged parametr in your query. Feb 5, 2018 at 12:44
  • @MaximSarandi paged is a parameter that is used to page the page content. When you use it, it means that the page can not be paged which might be good enough for 99% of use cases, but it is just one of the hacks I referred to. Feb 5, 2018 at 12:52
  • paged - is a paramater wich build paged or paginated content. And this solution from codex wordpress. This is not hack. this is true solution for pagination. WP_Query() has functionality to build paginated content. See official documentation. Feb 5, 2018 at 12:56
  • again , you have a page which can be paginated and then a paginated content inside. When you pass a pagination parameter, to which of them it should apply? As much as the codex is full of bad practice advice I will be surprised to see that there is anything there that claims that this is the way to do secondary pagination. Maybe you can use that specific function while using a new url parameter, which is what I refer to in "write your own pagination", but than you maight run into other issues with canonical redirect and maybe other things. Feb 5, 2018 at 13:18
  • Se my answer under. On page posts preindet by custom wp_query. And if you pass a paged var you should set in your query. like new WP_Query(array('paged' => get_query_var('page'))). And WP_Query will recieve paginated content. My code below is explain what i mean. Feb 5, 2018 at 13:25

Something like this might help you

$args = array(
    'end_size'  => 1,
    'mid_size'  => 1,
    'prev_next' => false,
    'type'      => 'list',
    'current'   => max( 1, get_query_var('page') ),
    'total'     => $query->max_num_pages,

In your query define get_query_var('page') like

'paged' => get_query_var('page') ?: 1,
  • The problem with this answer is that it assumes that wordpress will not check whether such a page as specified by the url exists, and return a 404 or do a canonical redirect for it. This might happen since wordpress core has no idea that there is a secondary loop on the page. If such a change in core will happen all the pages that you have written this way will stop working. I am not saying that this is likely to happen, but this is an undocumented usage of url parameters and you should not be surprised if for some reason it will get an official meaning which contradicts the way you use it Feb 5, 2018 at 14:08
  • ... or deprecate it. This also might never happen, but you are living on the edge when doing such things Feb 5, 2018 at 14:09
  • Maybe you're right, but this is official solution from wordpress documentation. And you haven`t better way to do pagination on custom page. One more way - AJAX pagination. Feb 5, 2018 at 14:21

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.