Search Hooks

Control how CelerSearch intercepts and processes WordPress search queries.

Query Interception

celersearch_should_intercept_query

Control whether CelerSearch handles a specific query.

PHP
add_filter('celersearch_should_intercept_query', function($should_intercept, $query) {
    // Don't intercept admin AJAX searches
    if (wp_doing_ajax() && is_admin()) {
        return false;
    }

    // Don't intercept queries with custom parameter
    if ($query->get('use_native_search')) {
        return false;
    }

    return $should_intercept;
}, 10, 2);
ParameterTypeDescription
$should_interceptboolDefault interception decision
$queryWP_QueryThe WordPress query object

Context Detection

celersearch_admin_area_type

Customize admin search area type detection.

PHP
add_filter('celersearch_admin_area_type', function($area_type, $query, $post_type) {
    // Custom admin area for specific post type
    if ($post_type === 'my_custom_type') {
        return 'admin_my_custom_search';
    }
    return $area_type;
}, 10, 3);

celersearch_area_type

Determine search area type for custom contexts.

PHP
add_filter('celersearch_area_type', function($area_type, $query) {
    // BuddyPress members directory
    if (function_exists('bp_is_members_directory') && bp_is_members_directory()) {
        return 'buddypress_members_search';
    }

    // bbPress forums
    if (function_exists('is_bbpress') && is_bbpress()) {
        return 'bbpress_forum_search';
    }

    return $area_type;
}, 10, 2);

celersearch_browse_area_types

Customize which area types are considered "browse" areas (areas that don't require a search term).

PHP
add_filter('celersearch_browse_area_types', function($browse_areas) {
    // Add a custom browse area type
    $browse_areas[] = 'my_custom_browse';

    return $browse_areas;
});
ParameterTypeDescription
$browse_areasarrayArea type strings. Default: ['woocommerce_shop_browse']

Browse areas allow CelerSearch to intercept queries even without a search term, enabling features like faceted browsing on shop/archive pages.


Index Selection

celersearch_select_index

Programmatically select which index to use.

PHP
add_filter('celersearch_select_index', function($index, $query) {
    // Use products index for shop pages
    if (function_exists('is_shop') && is_shop()) {
        return get_products_index();  // Your helper function
    }

    // Use different index for logged-in users
    if (is_user_logged_in()) {
        return get_members_index();
    }

    return $index;
}, 10, 2);
ParameterTypeDescription
$indexBaseIndex|nullCurrently selected index
$queryWP_QueryThe WordPress query

Priority order:

  1. Explicit WP_Query parameters (celersearch_index)
  2. Search area configuration
  3. This filter
  4. Default index from settings

Search Parameters

celersearch_search_params

Modify parameters before search execution.

PHP
add_filter('celersearch_search_params', function($params, $query, $index) {
    // Add custom sorting
    $params['sort'] = ['is_featured:desc', 'created_at:desc'];

    // Add custom filter
    if (!is_user_logged_in()) {
        $params['filter'] = 'visibility = "public"';
    }

    // Increase results limit
    $params['limit'] = 50;

    return $params;
}, 10, 3);
ParameterTypeDescription
$paramsarraySearch parameters
$queryWP_QueryThe WordPress query
$indexBaseIndexThe index being searched

Available parameters:

  • q - Search query string
  • limit - Max results
  • offset - Pagination offset
  • filter - Filter string (syntax depends on provider)
  • sort - Array of sort rules
  • highlighting - Highlighting configuration

Sorting

celersearch_sort_options

Filter the map of sort keys to engine sort rules. This runs in BaseIndex::resolve_sort(), so it applies to every index and every path that resolves a sort key — search area default sorts, view sorting (?sort= in the views REST API), and custom callers.

PHP
add_filter('celersearch_sort_options', function($sort_map, $sort_key, $index) {
    // Add popularity sort (products)
    $sort_map['popularity'] = ['total_sales:desc'];

    // Add price sorting
    $sort_map['price']      = ['price:asc'];
    $sort_map['price-desc'] = ['price:desc'];

    return $sort_map;
}, 10, 3);
ParameterTypeDescription
$sort_maparraySort key => sort rules mapping
$sort_keystringThe requested sort key
$indexBaseIndexThe index resolving the sort

Default sort options (field names come from the index's sort field map):

KeyPosts indexProducts index
date['created_at:desc']['post_date:desc']
date-asc['created_at:asc']['post_date:asc']
title['title:asc']['post_title:asc']
title-desc['title:desc']['post_title:desc']

Unknown sort keys resolve to an empty array (relevance order).


Search Results

celersearch_search_results

Modify results after search execution.

PHP
add_filter('celersearch_search_results', function($results, $query, $index) {
    // Add extra data to each hit
    foreach ($results['hits'] as &$hit) {
        $post_id = $hit['post_id'] ?? null;
        if ($post_id) {
            $hit['view_count'] = (int) get_post_meta($post_id, 'views', true);
            $hit['is_bookmarked'] = user_has_bookmarked($post_id);
        }
    }

    // Log search for analytics
    log_search_query($query->get('s'), count($results['hits']));

    return $results;
}, 10, 3);
ParameterTypeDescription
$resultsarraySearch results from search engine
$queryWP_QueryThe WordPress query
$indexBaseIndexThe index searched

Results structure:

PHP
[
    'hits' => [...],
    'estimatedTotalHits' => 150,
    'processingTimeMs' => 5,
]

Pinned Searches

celersearch_apply_pinning

Control whether pinned (curated) search results are applied for a query. When the query exactly matches a pinned search label/alias, the curated, ordered set replaces engine results; contains-match keywords boost curated documents on top of engine results. Pinning is storefront-facing, so by default it is applied outside admin areas and skipped in admin.

PHP
add_filter('celersearch_apply_pinning', function($apply, $query, $area_type) {
    // Disable pinning for editors previewing real relevance
    if (current_user_can('edit_posts')) {
        return false;
    }

    return $apply;
}, 10, 3);
ParameterTypeDescription
$applyboolWhether to apply pinning (default: true outside admin areas, false in admin)
$queryWP_QueryThe WordPress query
$area_typestring|nullThe detected search area type

celersearch_pinned_search_max_records

Filter the maximum number of records that can be pinned to a single pinned search in the admin UI.

PHP
add_filter('celersearch_pinned_search_max_records', function($max) {
    return 200;  // Default: 100
});
ParameterTypeDescription
$maxintMaximum pinned records per search (default: 100)

Values of 0 or less fall back to the default. The cap exists because the curated set is fetched per-document at search time and a curated list isn't meaningfully paginated.


View Result Formatting

celersearch_view_search_hit

Customize individual search hit data before rendering in a view.

This is the view equivalent of celersearch_autocomplete_hit. Use it to add, modify, or remove fields on each hit before the view template displays it.

PHP
add_filter('celersearch_view_search_hit', function($hit, $raw_hit, $post, $view) {
    // Add price for WooCommerce products
    if ($post->post_type === 'product') {
        $product = wc_get_product($post);
        $hit['price'] = $product->get_price_html();
        $hit['in_stock'] = $product->is_in_stock();
        $hit['rating'] = $product->get_average_rating();
    }

    // Add custom thumbnail size
    $hit['thumbnail'] = get_the_post_thumbnail_url($post, 'medium');

    // Add reading time for blog posts
    if ($post->post_type === 'post') {
        $word_count = str_word_count(wp_strip_all_tags($post->post_content));
        $hit['read_time'] = ceil($word_count / 200) . ' min read';
    }

    return $hit;
}, 10, 4);
ParameterTypeDescription
$hitarrayFormatted hit data for the view
$raw_hitarrayRaw hit from the search engine
$postWP_PostThe WordPress post object
$viewViewThe view being rendered

Default hit structure:

PHP
[
    'id'        => 123,
    'title'     => 'Post Title',
    'url'       => 'https://example.com/post-title',
    'excerpt'   => 'Short description...',
    'type'      => 'post',
    'thumbnail' => 'https://example.com/image.jpg',
    'date'      => '2024-01-15',
    'author'    => 'John Doe',
]

Example: Conditionally modify hits per view

PHP
add_filter('celersearch_view_search_hit', function($hit, $raw_hit, $post, $view) {
    // Only modify hits in the "products" view
    if ($view->slug !== 'products') {
        return $hit;
    }

    // Add stock badge
    $product = wc_get_product($post);
    $hit['badge'] = $product->is_in_stock() ? 'In Stock' : 'Out of Stock';
    $hit['badge_class'] = $product->is_in_stock() ? 'badge-success' : 'badge-danger';

    return $hit;
}, 10, 4);

Post Status Filtering

celersearch_search_statuses

Control which post statuses appear in results.

PHP
add_filter('celersearch_search_statuses', function($statuses, $query, $area_type) {
    // Admins see all statuses
    if (current_user_can('edit_others_posts')) {
        return ['publish', 'draft', 'pending', 'private', 'future'];
    }

    // Authors see their own drafts
    if (is_user_logged_in()) {
        return ['publish', 'private'];
    }

    // Public only sees published
    return ['publish'];
}, 10, 3);

Taxonomy Filtering

celersearch_unfilterable_taxonomies

Filter the taxonomies that are skipped when translating a WP_Query tax_query into engine filters. These taxonomies aren't stored as filterable facets in the index, so their clauses must be dropped rather than sent to the engine — which would otherwise reject the filter.

PHP
add_filter('celersearch_unfilterable_taxonomies', function($taxonomies, $query) {
    // A private taxonomy that is never indexed
    $taxonomies[] = 'internal_flags';

    return $taxonomies;
}, 10, 2);
ParameterTypeDescription
$taxonomiesstringTaxonomies to skip. Default: ['product_visibility', 'product_shipping_class'] (WooCommerce internals — the products index skips these at index time too)
$queryWP_Query|nullThe WordPress query being translated

Highlighting

celersearch_highlighting_enabled

Enable or disable search result highlighting.

PHP
// Disable highlighting globally
add_filter('celersearch_highlighting_enabled', '__return_false');

// Conditional highlighting
add_filter('celersearch_highlighting_enabled', function($enabled) {
    // Disable for AJAX requests
    return !wp_doing_ajax();
});

celersearch_highlighting_enable_bundled_styles

Control bundled highlighting CSS.

PHP
// Disable bundled styles (use your own)
add_filter('celersearch_highlighting_enable_bundled_styles', '__return_false');

Then add your own styles:

CSS
.celersearch-highlight {
    background-color: #ffeb3b;
    font-weight: bold;
    padding: 0 2px;
}

Complete Example

Combine multiple hooks for a complete customization:

PHP
// 1. Control interception
add_filter('celersearch_should_intercept_query', function($intercept, $query) {
    // Only intercept main queries with search term
    return $intercept && $query->is_main_query() && $query->get('s');
}, 10, 2);

// 2. Select appropriate index
add_filter('celersearch_select_index', function($index, $query) {
    $post_type = $query->get('post_type');

    if ($post_type === 'product') {
        return get_index_by_slug('products');
    }

    return $index;
}, 10, 2);

// 3. Customize search params
add_filter('celersearch_search_params', function($params, $query, $index) {
    // Boost recent content
    $params['sort'] = ['_rankingScore:desc', 'created_at:desc'];

    // Filter by category if set
    if ($cat = $query->get('cat')) {
        $params['filter'] = "taxonomies.category.id = {$cat}";
    }

    return $params;
}, 10, 3);

// 4. Enhance results
add_filter('celersearch_search_results', function($results, $query, $index) {
    // Track search
    track_search($query->get('s'), count($results['hits']));

    return $results;
}, 10, 3);