How to List Posts on a Page Using ACF Field Values in Shortcodes?

Here’s how you can list posts on a page using ACF field values within a shortcode. This solution involves adding a custom PHP function to your WordPress theme’s functions.php file or a custom plugin.

I’ll provide the PHP code for the shortcode, along with instructions on how to use it.

<?php
/**
 * Custom Shortcode to List Posts Based on ACF Field Value
 *
 * This code should be added to your theme's functions.php file
 * or a custom WordPress plugin.
 */

function custom_acf_post_list_shortcode($atts) {
    // Define default attributes for the shortcode
    $atts = shortcode_atts(
        array(
            'field_name'  => '', // The name of your ACF field
            'field_value' => '', // The value to match in the ACF field
            'post_type'   => 'post', // The post type to query (e.g., 'post', 'page', 'custom_post_type')
            'posts_per_page' => -1, // Number of posts to show (-1 for all)
            'order'       => 'DESC', // Order of posts (ASC or DESC)
            'orderby'     => 'date', // How to order posts (e.g., 'date', 'title', 'menu_order')
        ),
        $atts,
        'acf_posts' // The name of your shortcode
    );

    $field_name  = sanitize_text_field($atts['field_name']);
    $field_value = sanitize_text_field($atts['field_value']);
    $post_type   = sanitize_text_field($atts['post_type']);
    $posts_per_page = intval($atts['posts_per_page']);
    $order       = sanitize_text_field($atts['order']);
    $orderby     = sanitize_text_field($atts['orderby']);

    // Validate required attributes
    if (empty($field_name) || empty($field_value)) {
        return '<p>Error: Please specify both "field_name" and "field_value" in the [acf_posts] shortcode.</p>';
    }

    // Prepare the meta query for WP_Query
    $meta_query = array(
        array(
            'key'     => $field_name,
            'value'   => $field_value,
            'compare' => '=', // You can use '=', 'LIKE', 'IN', etc.
            'type'    => 'CHAR', // Data type of the field (e.g., 'CHAR', 'NUMERIC', 'DATE')
        ),
    );

    // Arguments for WP_Query
    $args = array(
        'post_type'      => $post_type,
        'posts_per_page' => $posts_per_page,
        'order'          => $order,
        'orderby'        => $orderby,
        'meta_query'     => $meta_query,
        'post_status'    => 'publish', // Only get published posts
        'suppress_filters' => false, // Important for ACF to work correctly with meta_query
    );

    // Create a new WP_Query instance
    $query = new WP_Query($args);

    $output = '';

    // Check if there are any posts
    if ($query->have_posts()) {
        $output .= '<ul>';
        while ($query->have_posts()) {
            $query->the_post();
            $output .= '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
        }
        $output .= '</ul>';
        // Restore original post data
        wp_reset_postdata();
    } else {
        $output .= '<p>No posts found matching the criteria.</p>';
    }

    return $output;
}
add_shortcode('acf_posts', 'custom_acf_post_list_shortcode');

How to Use This Code:

  1. Add the Code to WordPress:
    • Recommended: Create a custom plugin. This is the best practice as it keeps your functionality separate from your theme, so it won’t be lost if you change themes.
    • Alternative: Add the code to your theme’s functions.php file. Go to Appearance > Theme File Editor (or use an FTP client/cPanel file manager) and open functions.php. Paste the code at the end of the file, before the closing ?> tag if it exists.
  2. Using the Shortcode in a Page or Post: Once the code is added, you can use the [acf_posts] shortcode in any page, post, or even a text widget in WordPress.Here are some examples:
    • Basic Usage (matching a specific value for an ACF field named ‘city’):
        [acf_posts field_name="city" field_value="New York"]
       
    • Specifying a Custom Post Type (e.g., ‘event’ post type, matching ‘status’ field with ‘upcoming’):
       
      [acf_posts field_name="status" field_value="upcoming" post_type="event"]
      
    • Limiting the number of posts and ordering by title:
       
      [acf_posts field_name="category_type" field_value="premium" posts_per_page="5" orderby="title" order="ASC"]
      

Explanation:

  • custom_acf_post_list_shortcode($atts) function: This is the core function that runs when the shortcode [acf_posts] is encountered.
  • shortcode_atts(): This function merges the default attributes with the attributes provided in the shortcode, ensuring that all necessary parameters have a value.
  • sanitize_text_field() and intval(): These are crucial for security, sanitizing the input from the shortcode attributes.
  • $meta_query: This is the key part for ACF integration. It tells WP_Query to look for posts where a specific custom field (key) has a certain value.
    • 'compare' => '=': Means the value must exactly match. You can change this to LIKE (for partial matches), IN (if field_value is a comma-separated list), etc.
    • 'type' => 'CHAR': Specifies the data type of the custom field. Common types include CHAR (text), NUMERIC, DATE, DATETIME, DECIMAL, SIGNED, UNSIGNED. Choose the one that matches your ACF field’s data type for accurate comparisons.
  • WP_Query: This is the standard WordPress class for querying posts. It uses the $args array to define what posts to retrieve.
  • Looping through posts: if ($query->have_posts()) { ... } checks if any posts were found. while ($query->have_posts()) { $query->the_post(); ... } iterates through each post, making its data available for functions like get_permalink() and get_the_title().
  • wp_reset_postdata(): This is essential after using a custom WP_Query to restore the global post data to the main query, preventing conflicts with other parts of your page.
  • add_shortcode('acf_posts', 'custom_acf_post_list_shortcode');: This line registers your shortcode with WordPress, linking the shortcode tag acf_posts to your PHP function.

This shortcode provides a flexible way to display dynamic lists of posts based on your Advanced Custom Fields data.

Related Posts


Advanced WordPress Query: meta_key Filtering with Custom Order By meta_key

An advanced WordPress query that filters by meta_key and orders the results by another meta_key. Her...

Why Apple Pay Isn’t Showing on WooCommerce Authorize.Net Checkout (SkyVerge)

It’s understandable to be frustrated when you’ve meticulously followed all the steps for...

Media Gallery Preview Images Not Updating After Replacing via Media Library (WPBakery Grid Fix)

Troubleshooting Guide: WPBakery Media Grid Thumbnails Not Updating This guide will help you resolve ...

How to Retain Local Storage When Changing WooCommerce Payment Method?

When users switch payment methods on the WooCommerce checkout page, local storage data may reset, ca...

Recent Posts