facetwp_index_row
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:
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:
- Overwrite/change values for a facet choice.
- Remove one or more facet choices (by setting the
$params['facet_value']
value to an empty string). - Prevent one or more posts from showing up when using a facet.
- Show only specific term levels in a taxonomy-based facet.
- Split a facet choice into multiple choices.
- Insert new facet choices (with the
insert()
function). - Combine multiple facet choices into one choice.
- Combine multiple facet sources (by indexing one facet into another).
- Index custom fields with serialized data
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 child terms and deeper levels. In other words, skip the 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'] < 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 these last two examples 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.
Exclude one or more posts from a facet
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, or the following approach:
Exclude posts with a specific term from being indexed for all facets
To prevent posts that have a specific term from being indexed for all facets, 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_id = $params['post_id']; $excluded_terms = [ 'my_term', 'my_other_term' ]; // Add terms to be excluded $taxonomy = 'product_cat'; // The taxonomy that contains the terms foreach ( $excluded_terms as $term ) { if ( has_term( $term, $taxonomy, $post_id ) ) { $params['facet_value'] = ''; // Skip this row break; } } return $params; }, 10, 2 );
As in the previous example, this will exclude the specified posts from the results if they would normally show up when filtering with any facet.
And also here, 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.
As an alternative to the above code, you can also 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
. This could for example be used to create a Slider facet showing years, using the Post Date as data source.
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 );