I have set up a custom post type called 'Events'. For reasons that I'm not going to get into, I chose not use archive-events.php as the archive template for my Events. Instead, I decided to create a custom page template, page-upcoming-events.php, to use as an archive.

I wrote a custom query in this template to pull in events. I am also limiting posts_per_page to 4. I've successfully added pagination links using the previous_posts_link() and next_posts_link() functions.

These functions are generating links to the expected urls: /upcoming-events/page/2/, etc.

On page 1, I get the first 4 events and the next events link.

The issue I'm having is that when I go to page 2, I get a 404 error, not events 5-8.

How do I add properly add pagination to a custom page template?

2 Answers 2


This is what I do for paging. I hope it helps you get on the right track, it may be overkill for what you are trying to do...

First I set $paged:

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

Then build your $args array, make sure to call in:

'paged' => $paged

Run your query including the needed functions for paging (this is a sample, change what you need to make it yours):

        //the query using arguments above
        $wp_query = new WP_Query( $args );

        //use the query for paging
        $wp_query->query_vars[ 'paged' ] > 1 ? $current = $wp_query->query_vars[ 'paged' ] : $current = 1;

        //set the "paginate_links" array to do what we would like it it. Check the codex for examples http://codex.wordpress.org/Function_Reference/paginate_links
        $pagination = array(
            'base' => @add_query_arg( 'paged', '%#%' ),
            //'format' => '',
            'showall' => false,
            'end_size' => 4,
            'mid_size' => 4,
            'total' => $wp_query->max_num_pages,
            'current' => $current,
            'type' => 'plain'

        //build the paging links
        if ( $wp_rewrite->using_permalinks() )
            $pagination[ 'base' ] = user_trailingslashit( trailingslashit( remove_query_arg( 's', get_pagenum_link( 1 ) ) ) . 'page/%#%/', 'paged' );

        //more paging links
        if ( !empty( $wp_query->query_vars[ 's' ] ) )
            $pagination[ 'add_args' ] = array( 's' => get_query_var( 's' ) );

        //run the query
        if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post();

All that's left is to tell the page where you want the page links:

        //print the paging links to the page
        echo '<div class="pydPaging">' . paginate_links($pagination) . '</div>';

Again, this may be overkill, but it works well.

  • the paginate_links($pagination) function is returning empty for me
    – AGrush
    Apr 14, 2022 at 14:05

Are you sure that you don't have a page with the same name of the custom post type? If you do, the permalink rewrite rules will get confused and trigger a 404.

A very simple solution is: The page that lists the custom post types is called in plural (eg. products) and the actual post type name is in singular (eg. product). So they don't conflict and it's all fine.

Also always make sure to rewrite your .htaccess file when creating a new Custom Post Type.

Your Answer

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

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