Editor’s note: The following blog post was written in 2015. We can’t guarantee the accuracy of the code and presented solutions, but we’ve chosen to keep this blog post live for those who still find the information useful.
I encountered this issue last month when I was working through QA tasks; the client was searching a specific keyword phrase and wondering why one of the most prominent pages on the site (that featured that phrase) wasn’t being returned in results. I saw that the page was an archive for the custom post type “Products” and added that to the array of post types available to the search query:
function wds_cpt_search( $query ) { // If we're on the search page, working with the main query, and searched something... if ( is_search() && $query->is_main_query() && $query->get( 's' ) ){ // Include our product CPT. $query->set( 'post_type', array( 'post', 'page', 'product', // Our Product CPT. ) ); } } add_filter('pre_get_posts', 'wds_cpt_search');
But I still wasn’t seeing the page show up in results.
Looking at the Product post type, I saw that we were adding nearly all of our content to each Product via fields in a custom meta box. The keyword phrase I was looking for was specifically being entered into a WYSIWYG field via our CMB2 plugin. I checked and made sure the Product custom post type arguments for public
and publicly_queryable
were both set to true so it was available to the search query.
function wds_register_product_cpt() { // Register our product CPT. register_post_type( 'product', array( 'public' => true, 'publicly_queryable' => true, 'label' => __( 'Products', 'textdomain' ), ) ); } add_action( 'init', 'wds_register_product_cpt' );
Everything looked good there, so I set about building a custom search query that included the meta fields for each post being searched. By default, WordPress only includes post_title and post_content in its search query.
HANDY TIP: I tested two plugins, WP Search Everything and Relevanssi in the course of working on this issue and they both make it very easy to return all data from all post types in your site search if you want to skip the coding.
The Custom Field Parameters available to WP_Query
via WP_Meta_Query
are extremely handy (once I got over the impulse to just pop a SQL query into a function and call it good).
I just needed to return text from a single custom field, but the Codex page has a terrific breakdown of different ways to translate queries like “Show products where color=orange OR color=red AND size=small” into arguments you can pass to a new WP_Query
object.
My query ended up being a little simpler than that but once I added a function to filter through pre_get_posts
that used the following query, I got exactly the results I was looking for!
function wds_cpt_search( $query ) { // If we're on the search page, working with the main query, and someone searched for something... if ( is_search() && $query->is_main_query() && $query->get( 's' ) ) { // Add the CPT's to include in search. $query->set( 'post_type', array( 'post', 'page', 'product' // Especially our product CPT. ) ); // Search meta fields. $query->set( 'meta_query', array( // Search our wysiwyg field for the field they searched for. array( 'key' => 'wysiwyg', 'value' => $query->get( 's' ), 'compare' => 'LIKE', ), ) ); } } add_action( 'pre_get_posts', 'wds_cpt_search' );