During a process called indexing, FacetWP analyzes your site and stores facet data into a custom database table for quick lookups.

How to run the indexer

FacetWP indexer buttonsWhenever facets are added or edited, save your changes and then press the Re-index button. This completely rebuilds the index table.

If you press the Stop indexer button while the indexer is running, the index will remain incomplete until the next time you re-index.

While the indexer is running, you can click the rotating icon to see its progress.

It’s recommended to keep the FacetWP settings screen open while the indexer is running.

When to run the indexer

In general, FacetWP will let you know when you need to re-index, by displaying a message in the top right corner of the admin screen after you save facet settings.

Re-indexing is only needed:

Other indexing actions

Show indexable post types

FacetWP indexing: show indexable post typesLists all post types that will be indexed. If a desired post type is not in the list, make sure that the exclude_from_search parameter of the register_post_type() function is set to false (and re-index afterwards).

Alternatively, you could use the facetwp_indexer_query_args filter to force a non-searchable post type to be indexed.

Purge the index table

FacetWP Indexing: purge the index tableDeletes and re-creates the facetwp_index database table. This can be helpful in resolving database migration issues or sometimes with other issues like a “The index table is empty” message.

Make sure to re-index again after purging the index table.

Common indexing issues

Solving a stalled indexer

The indexer can stall occasionally: the server/WordPress ran out of memory, there was a power outage, etc. Fortunately, FacetWP includes built-in resume functionality. It should resume automatically after a minute or two, assuming you keep the FacetWP settings screen open.

If you do notice a stalled indexer, check your web server’s PHP error log for any clues.

If you see a “The index table is empty” message during indexing, click the Re-index button again to re-start the indexer.

If your site is behind a .htpasswd login, the indexer might be blocked from resuming. See the solution below.

If your site is hosted on WP Engine, see the fix below.

Solving issues with indexing post types

When you try to re-index and you get a “The index table is empty” message, or if certain post types are not getting indexed, check if the exclude_from_search parameter of the register_post_type() function is set to false (and re-index afterwards).

The exclude_from_search query parameter determines whether to exclude posts with this post type from the front-end WordPress search results. FacetWP by default only indexes searchable post types.

FacetWP indexing: show indexable post typesYou can check which post types FacetWP indexes with the “Show indexable post types” action of the “Re-index” button in FacetWP’s settings.

If you want to index and filter post types that you don’t want in your search results, it is also possible to force FacetWP to index non-searchable post types, with the facetwp_indexer_query_args hook. See the hook’s usage example.

Solving indexing issues for password-protected sites

To bypass PHP timeout issues, FacetWP’s indexer makes a series of HTTP requests to itself. If your site uses HTTP Basic Authentication (.htpasswd), you’ll need to tell FacetWP how to log in.

Add the following into functions.php or into the Custom Hooks add-on:

add_filter( 'http_request_args', function( $args, $url ) {
    if ( 0 === strpos( $url, get_site_url() ) ) {
        $args['headers'] = [
            'Authorization' => 'Basic ' . base64_encode( 'YOUR_USERNAME:YOUR_PASSWORD' )
        ];
    }
    return $args;
}, 10, 2 );

Solving indexing issues with WP Engine

If you are hosting your website on WP Engine and you are experience problems with FacetWP’s indexer stalling or not indexing all your posts, try adding the following line to wp-config.php:

define( 'WPE_GOVERNOR', false );

WP Engine limits long queries (longer than 1024 characters) for performance reasons. The above line in wp-config.php prevents that.

How to trigger the indexer programmatically

Use the following code to programmatically do a full re-index:

FWP()->indexer->index();

If you want to re-index a single post instead, set the $post_id parameter:

$post_id = 12345; // must be an integer
FWP()->indexer->index( $post_id );

Trigger periodic re-indexing with WP-Cron

If you do need to schedule a periodic re-index with WP-Cron, you can use the sample plugin below. It runs hourly but you can adjust the schedule as needed:

/*
Plugin Name: FacetWP Schedule Indexer
Plugin URI: https://facetwp.com/
Description: Runs indexer periodically by cron
Version: 1.0
Author: FacetWP, LLC
*/

add_action( 'fwp_scheduled_index', 'fwp_scheduled_index' );
function fwp_scheduled_index() {
  FWP()->indexer->index();
}

register_activation_hook( __FILE__, 'fwp_schedule_indexer_activation' );
function fwp_schedule_indexer_activation() {
  if ( ! wp_next_scheduled( 'fwp_scheduled_index' ) ) {
    wp_schedule_event( time(), 'hourly', 'fwp_scheduled_index' );
  }
}

register_deactivation_hook( __FILE__, 'fwp_schedule_indexer_deactivation' );
function fwp_schedule_indexer_deactivation() {
  wp_clear_scheduled_hook( 'fwp_scheduled_index' );
}

If you trigger re-indexing with WP-Cron, you may want to disable automatic indexing with the facetwp_indexer_is_enabled hook.

Trigger re-indexing with WP-CLI and server cron

If you prefer the command line, you can also use WP-CLI to manually trigger re-indexing.

Or, if you want to use a cron schedule to control indexing, you can use WP-CLI indexing commands in a server cron job. This can be useful too if you disabled WP-Cron for performance reasons, preventing you from using the above scheduling plugin.

With FacetWP’s built-in WP-CLI indexing command options you can also do partial re-indexes of only specific posts, post types, and facets, and you can purge the index table, as a whole or partially.

Re-indexing with WP-CLI (optimally triggered by a server cron job) is the recommended approach for indexing high-content sites, or sites with large amounts of content imported regularly. In these cases the automatic indexing process can become problematic. Using WP-CLI will give you full control over when the indexing process runs exactly, and at which frequency. In this approach, FacetWP’s automatic indexing can be turned off with the facetwp_indexer_is_enabled hook.

Trigger re-indexing with WP All Import

FacetWP doesn’t automatically index content added via the WP All Import plugin.

Fortunately, there are there are hooks that can be used that allow FacetWP to automatically detect and index imported content.

Disable automatic indexing

It is possible to disable automatic (re-)indexing process, with the facetwp_indexer_is_enabled hook:

add_filter( 'facetwp_indexer_is_enabled', '__return_false' );

This can be useful if you are using WP-CLI or WP-Cron to trigger indexing, or if you want to (temporarily) pause automatic indexing when importing content.

It is also possible to disable automatic indexing for certain types of content.

How to index serialized data

With FacetWP, it’s possible to index custom fields stored as a serialized array.

Let’s say you have a facet named days_of_week that uses a custom field with the same name. In the database, an example postmeta row looks like this:

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

To index it, add the following code to functions.php, then hit the Re-index button.

<?php

function index_serialized_data( $params, $class ) {
    if ( 'days_of_week' == $params['facet_name'] ) {
        $values = (array) $params['facet_value'];
        foreach ( $values as $val ) {
            $params['facet_value'] = $val;
            $params['facet_display_value'] = $val;
            $class->insert( $params );
        }
        return false; // skip default indexing
    }
    return $params;
}
add_filter( 'facetwp_index_row', 'index_serialized_data', 10, 2 );

See also