Here is an answer I recently did on another question, the same as your. Because the answer was never upvoted or accepted, I could not mark this question as duplicate, so I have deleted the answer in the other post and reposting it here.
Please note, some points are not aimed at this issue and can be ignored, also, you will just need to make a few alterations on the values as I have not changed anything in the original post. So don't be alarmed by some of the info in the answer ;-)
REPURPOSED ANSWER
Here is a slight variation of an answer I have done on about the same scenario. What differs here is that you want less posts_per_page
on page one
STEP 1
Remove query_posts
. You should never ever use query_posts
Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).
Replace it with the default loop
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php if ( 'regularproducts' == get_post_type() ) : ?>
//CONTENT HERE
<?php endif; ?>
<?php if ( 'wpsc-product' == get_post_type() ) : ?>
//CONTENT HERE
<?php endif; ?>
<?php endwhile; endif; ?>
STEP 2
Use pre_get_posts
to alter the main query to add your custom post_types to the main query to display on the home page.
STEP 3
Now, get the posts_per_page
option set from the back end (which should be set to 300) and also set your offset
which we are going to use. That will be 200
as you will need 100 posts on page one and 300 on the rest.
If you don't want to alter the posts_per_page
option, you can then just simply set the variable $ppg
to 300
$ppg = get_option( 'posts_per_page' );
//$ppg = 300;
$offset = 200;
STEP 4
On page one, you'll need to subtract the offset
to posts_per_page
$query->set( 'posts_per_page', $ppp - $offset );
STEP 5
You must apply your offset
to all subsequent pages, otherwise you will get a repetition of the last post of the page on the next page
$offset = ( ( $query->query_vars['paged']-1 ) * $ppp ) - $offset;
$query->set( 'posts_per_page', $ppp );
$query->set( 'offset', $offset );
STEP 6
Lastly, you need to add your offset to found_posts
otherwise your pagination will will not show the last page
NOTE: This piece of code broke pagination on the search page. This is now fixed, see the updated code
function homepage_offset_pagination( $found_posts, $query ) {
$offset = 200;
if( $query->is_home() && $query->is_main_query() ) {
$found_posts = $found_posts + $offset;
}
return $found_posts;
}
add_filter( 'found_posts', 'homepage_offset_pagination', 10, 2 );
ALL TOGETHER
This is how your complete query will look like that should go into functions.php
function tax_and_offset_homepage( $query ) {
if ( !is_admin() && $query->is_home() && $query->is_main_query() ) {
$query->set( 'post_type', array( 'regularproducts', 'wpsc-product' ) );
$ppp = get_option( 'posts_per_page' );
//$ppp = 300;
$offset = 200;
if ( !$query->is_paged() ) {
$query->set( 'posts_per_page', $ppp - $offset );
} else {
$offset = ( ( $query->query_vars['paged']-1 ) * $ppp ) - $offset;
$query->set( 'posts_per_page', $ppp );
$query->set( 'offset', $offset );
}
}
}
add_action('pre_get_posts','tax_and_offset_homepage');
function homepage_offset_pagination( $found_posts, $query ) {
$offset = 200;
if( $query->is_home() && $query->is_main_query() ) {
$found_posts = $found_posts + $offset;
}
return $found_posts;
}
add_filter( 'found_posts', 'homepage_offset_pagination', 10, 2 );