SearchWP

Version 4 Documentation

Add WooCommerce Product Variations to Products

WooCommerce treats Product Variations differently than Products; they’re separate post types. Products are public and can be utilized in the way we’re used to working with post types, but Product Variations are different in that they’re set up as children of Products, but a different post type.

It’s a neat way to set things up, but we need to use a small bit of custom code to make Product Variations searchable.

The setup will involve teaching SearchWP about Product Variations, and having SearchWP index Product Variations as it is indexing the parent Products themselves. We’ll store the Product Variation data as ‘extra’ metadata for the Products, so when you search for Product Variation data the proper Product will be returned.

All hooks should be added to your custom SearchWP Customizations Plugin.

<?php
// Add WooCommerce Product Variation data to parent Products in SearchWP.
add_filter( 'searchwp\entry\data', function( $data, \SearchWP\Entry $entry ) {
// If this is not a Product, there's nothing to do.
if ( 'product' !== get_post_type( $entry->get_id() ) ) {
return $data;
}
$my_extra_meta_key = 'searchwp_product_variations';
// Retrieve all Variations.
$product_variations = get_posts( [
'post_type' => 'product_variation',
'posts_per_page' => -1,
'post_parent' => $entry->get_id(),
] );
if ( empty( $product_variations ) ) {
return $data;
}
// Customize the data indexed for each Variation.
$data['meta'][ $my_extra_meta_key ] = array_filter( $product_variations, function( $variation ) {
$variation->searchwp_variation_data = [
'title' => get_the_title( $variation->ID ),
'content' => $variation->post_content,
'sku' => get_post_meta( $variation->ID, '_sku', true ),
];
return $variation;
} );
return $data;
}, 20, 2 );
// Add our Extra Meta entry to SearchWP's UI.
add_filter( 'searchwp\source\attribute\options\special', function( $keys, $args ) {
if ( $args['attribute'] !== 'meta' ) {
return $keys;
}
// This key is the same as the one used in the searchwp\entry\data hook above, they must be the same.
$my_extra_meta_key = 'searchwp_product_variations';
$option = new \SearchWP\Option( $my_extra_meta_key, 'Product Variations' );
// If there's already a match, remove it because we want ours there.
$keys = array_filter( $keys, function( $option ) use ( $my_extra_meta_key ) {
return $my_extra_meta_key !== $option->get_value();
} );
// Add "Product Variations" Option
$keys[] = $option;
return $keys;
}, 20, 2 );

Note that the snippet indexes the following for each Product Variation:

  • Title
  • Content
  • SKU

You can add/remove/customize this list of attributes to index any content you would like for each Product Variation, it depends on what you would like to make searchable. 👍

With that snippet in place we can add Product Variations to the Custom Fields of our Engine:

Once you save your Engines, SearchWP will let you know the index needs to be rebuilt because of this change. The index can be rebuilt using the Rebuild Index button on the Engines tab of the SearchWP settings screen.

As the index rebuilds, SearchWP will pull in all Product Variations as it indexes Products, making all of that Product Variation data searchable and returning the parent Product when a Product Variation match is found.

We can take things a step further if you’d like. Given the setup above, searching for Product Variation data will return the Product itself as a result. With that result will be a permalink to the parent Product, which in many cases is desirable.

There are times when site visitors are very knowledgeable about your Products and may be searching for specific Product Variation data you’ve taught SearchWP to index.

For example: if you are selling TV’s and you have a parent Product “OLED TV” with a number of Product Variations for each screen size e.g. 60". If a customer searches for 60" OLED TV the result would be the OLED TV parent Product.

Wouldn’t it be great to automatically link to the 60" Product Variation when that happens? It would, and we can do exactly that!

All hooks should be added to your custom SearchWP Customizations Plugin.

<?php
// @link https://searchwp.com/documentation/knowledge-base/add-woocommerce-product-variations-to-products/
// When using SearchWP it's necessary to disable WooCommerce's insistance on
// automatically redirecting to a single search result without showing the
// search results page, when that happens this hook doesn't run!
// Willing to bet this can be edited to accommodate, tips are welcome!
add_filter( 'woocommerce_redirect_single_search_result', '__return_false' );
add_filter( 'post_type_link', function( $permalink, $post ) {
if ( ! is_search() || 'product' !== get_post_type( $post ) ) {
return $permalink;
}
$search_query = \SearchWP\Utils::get_string_from( get_search_query() );
// If this is a search for a Variation SKU we can bail out early.
$variation_from_sku = get_posts( [
'post_type' => 'product_variation',
'posts_per_page' => 1,
'fields' => 'ids',
'meta_query' => [ [
'key' => '_sku',
'value' => $search_query,
], ]
] );
// Make sure (if there is one) the Variation is for the parent Product.
if ( ! empty( $variation_from_sku ) ) {
// This is a Variation SKU.
$variation_id = absint( $variation_from_sku[0] );
$variation_obj = new WC_Product_Variation( $variation_id );
$attributes = $variation_obj->get_variation_attributes();
if ( empty( $attributes ) ) {
return $permalink;
}
return add_query_arg( $attributes, $permalink );
}
// Determine if this Product has any Variations.
$product_variations = get_posts( [
'post_type' => 'product_variation',
'posts_per_page' => -1,
'fields' => 'ids',
'post_parent' => $post->ID,
] );
if ( empty( $product_variations ) || ! class_exists( 'WC_Product_Variation' ) ) {
return $permalink;
}
// Check to see if any search terms match any Variation Attributes.
foreach ( $product_variations as $variation_id ) {
$variation_obj = new \WC_Product_Variation( $variation_id );
$attributes = $variation_obj->get_variation_attributes();
if ( empty( $attributes ) ) {
continue;
}
$search_query = \SearchWP\Utils::clean_string( $search_query );
foreach ( $attributes as $attribute_tax => $attribute_value ) {
foreach ( explode( ' ', $attribute_value ) as $value ) {
$value = \SearchWP\Utils::clean_string( \SearchWP\Utils::get_string_from( $value ) );
if ( false !== strpos( $search_query, $value ) ) {
$permalink = add_query_arg( [ $attribute_tax => urlencode( $attribute_value ) ], $permalink );
continue;
}
}
}
}
return $permalink;
}, 99, 2 );

With this snippet in place, we’ll check for any Product Variation Attributes that match the search string, and when we get a hit we’ll adjust the permalink to consider that Variation Attribute automatically.