Featured Posts in WordPress with ACF Pro

One problem we come across often in WordPress is giving the client the ability to create featured posts to display on a post or custom post type landing page (or anywhere for that matter.) There are quite a few options you can find with a quick Google search, but we’ve found there are limitations to many of these solutions. For example:

  1. Simply create a category term called ‘Featured’ and query the posts that are categorized as such.
    This is a good quick solution, but what if the user only wants one featured post. You could either only query the most recent post with this category, but maybe the client wants to feature a post that is further back than one they’ve previously featured? At this point, they’d have to find the original featured post and remove that category.
  2. Create a meta field checkbox to mark the post as featured and query based on that meta value.
    This presents the same set of issues and now you’d probably need to set something up in the edit window to show the client that these posts have this meta value.
  3. There’s always plugins
    Sure, but we’re trying to keep things light on the backend and we all know that the more plugins we add, the more potential there is for problems to arise. Not to mention, we have to make sure this plugin is up-to-date.

In this post, we’ll outline our programmatic solution involving the Advanced Custom Fields (ACF) plugin which we’re already using in all of our sites. There are so many great benefits to this plugin, and there’s no end in sight to the support this plugin offers. The people at ACF are always adding new useful features so (for now at least) we’re pretty confident in our usage of ACF on our sites. Our solution gives the client the ability to easily add or remove and reorder their featured posts.

So let’s get into it.

The basic concept for our solution is that we setup an options page for the post type in question. ACF makes this very easy. Let’s say we want to add a featured post in a post type called ‘project’. In your functions.php file add the following code:

if( function_exists('acf_add_options_page') ) {
  acf_add_options_sub_page(array(
    'title'      => 'Featured Project(s)',
    'parent'     => 'edit.php?post_type=project',
    'capability' => 'manage_options'
  ));
}

All we’re doing here is adding an options page in the dropdown of the post type area by using the parent argument as the edit.php for our custom post type. Then we limit the ability to edit this area to users with admin privileges:

Featured Project Selector

Next we’ll set up our featured project selector.

Jump over to your ACF Custom Fields area and add a new Field Group and title it whatever makes sense for your setup. Add a field. In our case, we’ll called it ‘Featured Project(s)’. NOTE: you should make sure your slug is unique. As of writing this post, all option page fields use the same parameter to query the fields: ‘option’. So if you have multiple fields with the same slug across different post type options pages, things may get messy. For this tutorial, ‘featured_projects’ will work fine.

Select Relationship for Field Type and select your custom post type in Filter by Post Type. For this post we’ll be selecting Post ID as the Return Format. Customize the remaining fields however you see fit. For instance, you can set a limit on the number of featured posts that can be selected by setting a value for Maximum posts or filter by a specific Taxonomy.

In the fields Location rules, select Options Page -> is equal to -> Featured Project(s).

Save your new fields.

Query the posts

Let’s say we want to display these on the homepage. Depending on your setup, we’ll either edit index.php or front-page.php. Add the following code where you want these posts to appear:

if ( $featured_projects = get_field('featured_projects', 'option') ) {  
  $projects_query = new WP_Query( array( 
    'post_type' => 'project', 
    'post__in' => $featured_projects,
    'posts_per_page' => count($featured_projects) // Optional
  ) );
  if ( $projects_query->have_posts()) :	
    while ( $projects_query->have_posts()): $projects_query->the_post();
      // Do post stuff here.
    endwhile;
    wp_reset_postdata();
  endif;
}

We’ll do a quick breakdown of what’s going on here:

  1. In the first if statement, we’re checking whether there are any featured projects selected.
  2. We’re identifying the post type with the ‘post_type’ parameter.
  3. We supply the ‘post__in’ parameter with an array of post ids that were selected in the Featured Projects selector. This tells the query which posts to get.
  4. Lastly, and this is optional, we’re telling the query how many posts we’re querying by counting the array of ids and supplying this number to the ‘posts_per_page’ parameter. This may come in handy if your default posts per page is set at a number lower than the number of featured posts that are selected. For instance, if your posts per page were set to 10 but your client selected 12 posts, only the first 10 would be displayed without the ‘posts_per_page’ parameter set.

There are a handful of other ways this can be setup and queried for instance, setting the Return Format to Post Object and pulling the values directly from the get_field( ‘featured_projects’, ‘option’ ) array. We’ve just found that more often than not, using WP_Query with the post__in parameter is the best method for our use cases.