Preserving sticky posts in templates

In this tutorial, we’ll show you how to keep sticky posts at the top of your FacetWP listings (all while using a single query).

The first step is to add a “show_sticky” argument to our existing Query Arguments. This is a custom argument that we’ll use to determine whether to handle sticky posts.

return array(
  'post_type' => 'post',
  'posts_per_page' => 10,
  'post_status' => 'publish',
  'show_sticky' => true,

Next, we’ll add the following code to our theme’s functions.php.

function fwp_preserve_sticky_posts( $query ) {
    if ( 'ids' == $query->get( 'fields' ) ) {

    if ( isset( $query->query_vars['show_sticky'] ) ) {
        $matches = array();
        $sticky = (array) get_option( 'sticky_posts' );
        $post_in = (array) $query->query_vars['post__in'];

        foreach ( $sticky as $post_id ) {
            if ( false !== ( $pos = array_search( $post_id, $post_in ) ) ) {
                $matches[ $pos ] = $post_id;
        ksort( $matches ); // preserve order of sticky posts
        $query->query_vars['orderby'] = 'post__in';
        $query->query_vars['post__in'] = array_merge( $matches, $query->query_vars['post__in'] );
add_action( 'pre_get_posts', 'fwp_preserve_sticky_posts' );

In this code, we first load all sticky posts (from the WP option named sticky_posts).

For each sticky post ID, we check for a match in the current query and, if one exists, we move that post ID to the top of the array. Finally, we sort by post__in, which is built-into WP_Query.