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:
- 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.phpfile. Go toAppearance > Theme File Editor(or use an FTP client/cPanel file manager) and openfunctions.php. Paste the code at the end of the file, before the closing?>tag if it exists.
- 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"]
- Basic Usage (matching a specific value for an ACF field named ‘city’):
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()andintval(): These are crucial for security, sanitizing the input from the shortcode attributes.$meta_query: This is the key part for ACF integration. It tellsWP_Queryto look for posts where a specific custom field (key) has a certainvalue.'compare' => '=': Means the value must exactly match. You can change this toLIKE(for partial matches),IN(iffield_valueis a comma-separated list), etc.'type' => 'CHAR': Specifies the data type of the custom field. Common types includeCHAR(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$argsarray 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 likeget_permalink()andget_the_title(). wp_reset_postdata(): This is essential after using a customWP_Queryto 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 tagacf_poststo your PHP function.
This shortcode provides a flexible way to display dynamic lists of posts based on your Advanced Custom Fields data.