Adding Sticky functionality to Custom Post Type Archives

In WordPress, Custom Post Types do not have Sticky functionality as a core feature. It is possible, I’m sure, to create it in certain cases—and I’m working on a project that requires it for archive-{customposttype}.php templates.

I have downloaded and installed a plugin, called Sticky Custom Post Types, which I read in this article could be used along with a little bit of PHP to get_option( ‘sticky_posts’ ) and reconfigure the array of the query currently being executed.

Read More

I know that the plugin works because using if (!is_sticky()) {et cetera} within the loop allows me to alter the output of the sticky (custom post type) posts.

I haven’t been able to successfully implement the code from the article—the order doesn’t seem to change at all when I place it at the top of my archive-{customposttype}.php template, nor have I been able to make it work through several other attempts. This is probably because I’m not very adept at PHP.

Another thing I tried is creating a new query, specifying that I want only sticky posts (which worked at showing me only sticky posts); trying to store that query in a variable, then calling wp_reset_query(), then creating another query specifying that I don’t want sticky posts, trying to store that in a variable, calling wp_reset_query() again; and then merging the two query arrays with array_merge().
Unfortunately my various implementations of this either broke the page, or succeeded at doing absolutely nothing, or only showed the second query’s output… and I deleted them out of scorn.

I don’t know if I’m going about this in the right way at all, really; and I’m sure plenty of people have confronted and overcome this issue. If anyone has any advice or code snippets to help me implement this feature, it’d be greatly appreciated.

To reiterate for the sake of clarity, I’m attempting to show sticky posts at the top of my archive pages for custom post types.

Related posts

Leave a Reply

2 comments

  1. I think the answer to your questions lies on the following webpage.

    Its author (Tareq Hasan) faced the same problem as we do and found a solution.

    https://tareq.co/2013/01/sticky-posts-in-custom-post-type-archives/

    Basically, you need to install the plugin you already have (Sticky Custom Post Types) and add a filter: (I paste the code here so if the page went down, we still have it.)

    The plugin is quite old but is very simple in the way it works so it still works perfectly with WordPress 4.2. Same apply to the below code snippet.

    Hope it helps you as it helped me.

    /**
     * Put sticky posts to top at custom post archives
     * Author: Tareq Hasan
     * Source: http://tareq.wedevs.com/2013/01/sticky-posts-in-custom-post-type-archives/
     * 
     * WordPress doesn't do any processing for sticky posts in custom post type archives.
     * It process sticky posts in homepage only (is_home()). This function processes
     * sticky posts at custom post archive page and puts them to the top of list.
     * 
     * @author Tareq Hasan (http://tareq.weDevs.com)
     *
     * @param array $posts array of queried posts
     * @return array
     */
    function wedevs_cpt_sticky_at_top( $posts ) {
    
        // apply the magic on post archive only
        if ( is_main_query() && is_post_type_archive() ) {
            global $wp_query;
    
            $sticky_posts = get_option( 'sticky_posts' );
            $num_posts = count( $posts );
            $sticky_offset = 0;
    
            // loop through the post array and find the sticky post
            for ($i = 0; $i < $num_posts; $i++) {
    
                // Put sticky posts at the top of the posts array
                if ( in_array( $posts[$i]->ID, $sticky_posts ) ) {
                    $sticky_post = $posts[$i];
    
                    // Remove sticky from current position
                    array_splice( $posts, $i, 1 );
    
                    // Move to front, after other stickies
                    array_splice( $posts, $sticky_offset, 0, array($sticky_post) );
                    $sticky_offset++;
    
                    // Remove post from sticky posts array
                    $offset = array_search($sticky_post->ID, $sticky_posts);
                    unset( $sticky_posts[$offset] );
                }
            }
    
            // Fetch sticky posts that weren't in the query results
            if ( !empty( $sticky_posts) ) {
    
                $stickies = get_posts( array(
                    'post__in' => $sticky_posts,
                    'post_type' => $wp_query->query_vars['post_type'],
                    'post_status' => 'publish',
                    'nopaging' => true
                ) );
    
                foreach ( $stickies as $sticky_post ) {
                    array_splice( $posts, $sticky_offset, 0, array( $sticky_post ) );
                    $sticky_offset++;
                }
            }
    
        }
    
        return $posts;
    }
    
    add_filter( 'the_posts', 'wedevs_cpt_sticky_at_top' );
    
  2. I’m implementing sticky posts in two custom post types, and I’ve just had a look at the plugin you mention here. It uses the sticky posts global option which WordPress uses to identify sticky posts – as far as I can see in the code, it will stick custom post types to the home page. What you need to do in your archive page is:

    Get sticky posts

    $sticky = get_option( 'sticky_posts' );
    

    Use a query to get only sticky posts for your post type, then output them at the top of the page

    $args = array(
        'posts_type' => [your custom post type slug],
        'post__in'  => $sticky
    );
    $sticky_query = new WP_Query( $args );
    while( $sticky_query->have_posts() ) {
        $sticky_query->next_post();
        echo '<li>' . get_the_title( $sticky_query->post->ID ) . '</li>';
    }
    wp_reset_postdata();
    

    Then modify the main query to exclude sticky posts using

    query_posts(array('post__not_in' => $sticky))