Extend WordPress search to include ACF field values so custom field content appears in search results.
WordPress search only looks at post titles and content by default. This snippet extends it to search ACF field values stored in wp_postmeta:
<?php
add_filter( 'posts_join', function ( $join, $query ) {
global $wpdb;
if ( $query->is_search() && $query->is_main_query() && ! is_admin() ) {
$join .= " LEFT JOIN {$wpdb->postmeta} AS acf_mt ON ({$wpdb->posts}.ID = acf_mt.post_id)";
}
return $join;
}, 10, 2 );
add_filter( 'posts_where', function ( $where, $query ) {
global $wpdb;
if ( $query->is_search() && $query->is_main_query() && ! is_admin() ) {
$search_term = $wpdb->esc_like( $query->get( 's' ) );
$where = preg_replace(
"/\({$wpdb->posts}\.post_title LIKE (.*?)\)/",
"({$wpdb->posts}.post_title LIKE $1) OR (acf_mt.meta_value LIKE '%{$search_term}%')",
$where
);
}
return $where;
}, 10, 2 );
add_filter( 'posts_distinct', function ( $distinct, $query ) {
if ( $query->is_search() && $query->is_main_query() && ! is_admin() ) {
return 'DISTINCT';
}
return $distinct;
}, 10, 2 );
To limit the search to specific ACF fields instead of all meta:
<?php
add_filter( 'posts_where', function ( $where, $query ) {
global $wpdb;
if ( $query->is_search() && $query->is_main_query() && ! is_admin() ) {
$search_term = $wpdb->esc_like( $query->get( 's' ) );
$allowed_keys = [ 'subtitle', 'summary', 'location' ];
$keys_in = "'" . implode( "','", array_map( 'esc_sql', $allowed_keys ) ) . "'";
$where = preg_replace(
"/\({$wpdb->posts}\.post_title LIKE (.*?)\)/",
"({$wpdb->posts}.post_title LIKE $1) OR (acf_mt.meta_key IN ({$keys_in}) AND acf_mt.meta_value LIKE '%{$search_term}%')",
$where
);
}
return $where;
}, 10, 2 );
Note: This approach searches all meta values. For large sites with many meta rows, consider using a dedicated search plugin like SearchWP or Relevanssi for better performance.