Overview

Modify individual facet values before they’re saved into FacetWP’s index table.

Parameters

  • $params | array | An associative array of data to be indexed (see below)
  • $class | object | The indexer class

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

$params = [ 'post_id' => 123, 'facet_name' => 'my_facet', 'facet_source' => 'tax/category', 'facet_value' => '45', 'facet_display_value' => 'My Test Category', 'term_id' => 0, 'parent_id' => 0, 'depth' => 0, 'variation_id' => 0 ];

Except for $params['facet_source'], the $params array keys/values correspond to columns in the facetwp_index table:

How it works

The facetwp_index_row hook is one of the most powerful and most used hooks in FacetWP, because it can manipulate the values and labels for each facet at the moment they are stored in the index table.

To get how this works exactly, it is important to understand how FacetWP’s facetwp_index database table is structured. Below is an example of a small part of this indexing table:

An example of a part of FacetWP's indexing table.
An example of a part of FacetWP’s indexing table.

As you can see, the post with ID 4070 has four rows indexed for a facet named categories. These four rows correspond to four choices in the categories facet, each of which will make this post appear in the results when this choice is clicked.

Each of the rows in the facetwp_index table has a value in the following nine columns:

Column Explanation
id The table row ID.
post_id The post ID.
facet_name The facet name.
facet_value The raw, technical facet value, as shown in the URL when this facet choice is selected. This is the term slug if the facet’s data source is a taxonomy.
facet_display_value The label of the facet choice, as shown in the facet itself in the front-end. This is the term name if the facet’s data source is a taxonomy.
term_id The term ID. Only used if the facet’s data source is a taxonomy, 0 otherwise.
parent_id The term parent ID. Only used if the facet’s data source is a hierarchical taxonomy, 0 otherwise.
depth The term depth. Only used if the facet’s data source is a hierarchical taxonomy, 0 otherwise.
variation_id The product variation ID. Only used if the indexed post is a WooCommerce product and indexing of product variations is enabled, 0 otherwise.

It is important to keep in mind that the facetwp_index_row hook runs once on the insertion of each of these table rows. So it runs for each post ID, for each facet, and then for each value that this post has stored for that facet’s data source (generally a custom field or one or more terms in a taxonomy).

While it is running, you have access to all of the above values for the current row, via the $params variable. You can use these values to manipulate the facet_value and facet_display_value (or the other values) for the row, and pass them back to $params just before the data is inserted into the row.

Good to know is that if you set the $params['facet_value'] variable to an empty string, the insertion of the whole row will be skipped. This can be useful if you want to prevent certain facet values from being indexed. For example, if you want to index only specific levels in a term hierarchy.

Another important thing to remember is that when a facet has a taxonomy set as its data source, the term slug is stored in facet_value and the term name in facet_display_value.

The access to the indexing process and its variables makes this hook very versatile. Some things you can do with it:

You can find a lot more examples in our code snippet library.

Usage examples

Index only specific term levels

Index only top-level terms (depth = 0):

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_facet_name' == $params['facet_name'] ) { // replace 'my_facet_name' with the name of your facet if ( $params['depth'] > 0 ) { $params['facet_value'] = ''; // don't index this row } } return $params; }, 10, 2 );

Index only the top-level terms (depth = 0) and their direct children (depth = 1):

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_facet_name' == $params['facet_name'] ) { // replace 'my_facet_name' with the name of your facet if ( $params['depth'] > 1 ) { $params['facet_value'] = ''; // don't index this row } } return $params; }, 10, 2 );

Index only the first-level direct child terms (depth = 1):

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_facet_name' == $params['facet_name'] ) { // replace 'my_facet_name' with the name of your facet if ( $params['depth'] !== 1 ) { $params['facet_value'] = ''; // don't index this row } } return $params; }, 10, 2 );

Note that this will last example will not work when the “Hierarchical” setting is enabled, in Checkboxes, Dropdown and fSelect facets. This is because in that case the facet values are rendered and re-ordered to display the hierarchy itself, which will not work when higher levels are absent.

To prevent one or more posts from being indexed for a certain facet, you can use the following code:

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { $post_ids = array( 123, 456, 789 ); // add your post IDs here if ( 'my_facet_name' == $params['facet_name'] && in_array( $params['post_id'], $post_ids ) ) { // replace 'my_facet_name' with the name of your facet $params['facet_value'] = ''; // don't index this row } return $params; }, 10, 2 );

This will exclude the specified posts from the results if they would normally show up when filtering with the specified facet.

Note that this code will not prevent these post(s) from showing up in the unfiltered results. To prevent posts from being in the results at all, you can adapt your query, or use the facetwp_pre_filtered_post_ids hook. Or, if you only want to prevent them from being in the filtered results, no matter which facet is used, you can use the facetwp_filtered_post_ids hook.

Combine facet choices

Combine multiple facet choices into one choice:

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'fruits' == $params['facet_name'] ) { // Replace 'fruits' with the name of your facet. $val = $params['facet_value']; if ( 'oranges' == $val || 'grapefruits' == $val || 'lemons' == $val ) { // Replace 'oranges'/'grapefruits'/'lemons' with the facet choices to combine (we use the technical name here). Note that || means OR. $params['facet_value'] = 'citrus-fruits'; // Replace 'citrus-fruits' with the new facet_value (technical name/slug). Don't use spaces or special characters. $params['facet_display_value'] = 'Citrus Fruits'; // Replace 'Citrus Fruits' with the new facet choice's display name. } } return $params; }, 10, 2 );

Important to distinguish here is that each facet choice consists of two values that are indexed and stored in the index table. The facet_value is its technical name (“slug”) as it appears in the URL after filtering. And the facet_display_value is the choice’s display value as it shows up in the facet itself in the front-end.

Another thing to notice is that in line 3 and 4 of the above example, we are using facet_value to select the choices that will be combined. You could also use facet_display_value here, as it is available in the hook’s parameters.

Split or add facet choices

This hook can also be used to add new rows to the indexing table, with the insert() function. The following code example splits comma-separated facet values into individual facet values. It then uses the insert() function to enter these values as new rows in the indexing table.

Say you have a facet with a choice apples, oranges, bananas. After implementing the below code, and doing a full re-index, you will now have three facet choices: apples, oranges, and bananas.

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_facet_name' == $params['facet_name'] ) { // Replace 'my_facet_name' with the name of your facet // Split the original facetwp_display_value by comma $values = explode(",", $params['facet_display_value']); // Store each separate value as a new row foreach ($values as $value) { $value = trim( $value ); // Remove any whitespace from the beginning and end of the new value $params['facet_value'] = $value; $params['facet_display_value'] = $value; $class->insert( $params ); } $params['facet_value'] = ''; // skip the original row } return $params; }, 10, 2 );

Remove facet choices

With this hook you can also remove facet choices. The easiest way to do this is with the facet’s value modifiers (if it has that setting). But in some situations, this will not work. For example, if you have a facet that uses categories as data source, and there are multiple terms with the same name, but different slugs. To remove these duplicate terms, you need to be able to select them by facet_value (the term slug), and not facet_display_value (the term name, as used in the facet’s “Value modifiers” setting).

The following example assumes three facet choices, all with the label “X-lock” and with slugs x-lock, x-lock-2 and x-lock-3. The snippet removes the two facet choices with slugs x-lock-2 and x-lock-3:

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { $exclude_values = array( 'x-lock-2', 'x-lock-3' ); // add the raw values / slugs of choices to remove if ( 'my_facet_name' == $params['facet_name'] && in_array( $params['facet_value'], $exclude_values ) ) { // replace 'my_facet_name' with the name of your facet $params['facet_value'] = ''; // don't index this row } return $params; }, 10, 2 );

Create a month/year facet

This hook can also be used to create a facet with years (or months and years) as facet choices.

First, create a facet (for example a Dropdown facet), and set its Data Source to Post Date (or any custom field that stores a date in the YYYY-MM-DD format).

Then add the following code to your (child) theme’s functions.php. Make sure to change my_facet_name to the name of your facet, and re-index:

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_facet_name' == $params['facet_name'] ) { // change "my_facet_name" to the name of your facet $raw_value = $params['facet_value']; $params['facet_value'] = date( 'Y-m', strtotime( $raw_value ) ); // Use "2023-11" for the facet choice in the URL $params['facet_display_value'] = date( 'F Y', strtotime( $raw_value ) ); // Use "November 2023" for the facet choice's display value } return $params; }, 10, 2 );

Using this example code, the facet will display choices formatted as November 2023, determined by the F Y format passed in the date() function for the facet_display_value in line 5. When selected, the facet choice will show as 2023-11 in the URL, as set in line 4 with the Y-m format.

These formats can be changed: for example to only show years just use Y. For abbreviated, 3-letter month names, use M instead of F. See PHP’s date() function for more formatting options.

Index a serialized array

Some custom fields store their values as a serialized array, which looks like this:

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

a:2:{i:0;s:6:"Monday";i:1;s:8:"Thursday";}

FacetWP will recognize some custom field types that do this (like ACF Checkboxes fields) and will automatically unserialize the value while indexing. But this will not always be the case. There are also situations in which FacetWP does not recognize the field as being serialized, for example if a facet uses an ACF Relationship field or Post Object field as its data source, and the related field is a field that stores its data serialized, like an ACF Checkboxes field.

In these situations, you can use the facetwp_index_row hook as shown in the example below. To index each value within a serialized array, it first needs to be unserialized. Then each value in the array can be inserted individually into the database. And last but not least, the original (serialized) value needs to be skipped over:

How to use custom PHP code?

PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info

add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_facet_name' == $params['facet_name'] ) { // Replace 'my_facet_name' with the name of your facet $values = maybe_unserialize( $params['facet_value'] ); if ( is_array( $values ) && ! empty( $values ) ) { foreach ( $values as $value ) { $params['facet_value'] = $value; // Set the choice's technical value (as seen in the URL). $params['facet_display_value'] = $value; // set the choice's display value (as seen in the facet). $class->insert( $params ); // insert each new value into the database as a new row. } $params['facet_value'] = ''; // skip the original row, by setting the technical value to nothing. } } return $params; }, 10, 2 );

More examples

See also