Back to Blog
Queryra Developer Filters: Two Hooks for Customising AI Search Indexing
guide

Queryra Developer Filters: Two Hooks for Customising AI Search Indexing

Two stable WordPress filters let developers extend what Queryra indexes — append content from any postmeta source via queryra_indexable_meta_content, or override which custom taxonomies are sent via queryra_indexable_taxonomies. Code examples for Pods, JetEngine, custom postmeta, and selective taxonomy lists.

RG
Rafal Gron
Founder, Queryra
May 14, 2026·7 min read

Queryra ships with two stable, officially supported WordPress filters that let developers extend what gets indexed for AI semantic search. They cover the two extension points that matter for non-standard sites: adding content from sources Queryra doesn't read natively (Pods, JetEngine, your own custom postmeta), and overriding which custom taxonomies get sent to the search index (whitelist, rename, exclude private taxonomies).

This post documents both filters with code examples for common use cases. Both are stable across plugin versions — adding new filters in future doesn't change the contract of these two.

Filter 1: queryra_indexable_meta_content

Append text from any source to a record's indexable content before it goes to the AI embedding. Useful when your site stores content in postmeta keys that aren't on Queryra's auto-extraction list (Elementor, Breakdance, Oxygen, Beaver Builder, ACF, Meta Box).

Signature:

apply_filters('queryra_indexable_meta_content', $content, $post_id);

  • $content *(string)* — the content that will be appended to the record's description field before sync. Starts empty.
  • $post_id *(int)* — the post being synced.
  • Return: modified $content string (any text you want included in the AI embedding).

### Example 1: Pods custom fields

Pods stores custom field values in standard WordPress postmeta under the field's name. Read them and append the text values to the indexable content:

add_filter('queryra_indexable_meta_content', function ($content, $post_id) {
    if (!function_exists('pods')) {
        return $content;
    }
    $pod = pods('book', $post_id);
    if (!$pod || !$pod->exists()) {
        return $content;
    }

    // Append a few Pods fields to the indexable content
    $extras = [];
    foreach (['summary', 'author_bio', 'editorial_notes'] as $field) {
        $value = $pod->display($field);
        if ($value) {
            $extras[] = $value;
        }
    }
    if ($extras) {
        $content .= ' ' . implode('. ', $extras);
    }
    return $content;
}, 10, 2);

### Example 2: JetEngine custom fields

JetEngine stores field values under their field key in postmeta. Append a few specific fields:

add_filter('queryra_indexable_meta_content', function ($content, $post_id) {
    $fields_to_index = ['_jet_specs', '_jet_features', '_jet_warranty'];
    foreach ($fields_to_index as $key) {
        $value = get_post_meta($post_id, $key, true);
        if (is_string($value) && trim($value) !== '') {
            $content .= ' ' . wp_strip_all_tags($value);
        }
    }
    return $content;
}, 10, 2);

### Example 3: Custom postmeta with a prefix

If you have your own custom postmeta naming convention (e.g. all keys prefixed _mysite_), iterate everything matching the prefix:

add_filter('queryra_indexable_meta_content', function ($content, $post_id) {
    $all_meta = get_post_meta($post_id);
    foreach ($all_meta as $key => $values) {
        if (strpos($key, '_mysite_') !== 0) continue;
        foreach ($values as $value) {
            if (is_string($value) && trim($value) !== '') {
                $content .= ' ' . wp_strip_all_tags($value);
            }
        }
    }
    return $content;
}, 10, 2);

Whatever you return is appended to the AI embedding text alongside the standard post_content, excerpt, attributes, and taxonomies. The semantic search index picks it up on the next sync.

Filter 2: queryra_indexable_taxonomies

Override the auto-detected list of custom taxonomies that Queryra sends to the search index. The plugin's default behaviour is to include every taxonomy registered with public => true (excluding built-ins like category, post_tag, product_cat/tag, product_brand — those are covered by dedicated fields). This filter lets you restrict, rename, or expand that auto-detected list.

Signature:

apply_filters('queryra_indexable_taxonomies', $taxonomies_map, $post);

  • $taxonomies_map *(array)* — auto-detected map of slug => "term1, term2" strings. E.g. ['book_genre' => 'fiction, classic', 'book_author' => 'F. Scott Fitzgerald'].
  • $post *(WP_Post)* — the post being synced.
  • Return: modified map. Whatever you return is sent to the Queryra API in the record's taxonomies field.

### Example 1: Whitelist specific taxonomies for a post type

Only send book_genre, book_author, book_era for the book post type — exclude everything else:

add_filter('queryra_indexable_taxonomies', function ($taxonomies_map, $post) {
    if ($post->post_type !== 'book') {
        return $taxonomies_map;
    }
    $allowed = ['book_genre', 'book_author', 'book_era'];
    return array_intersect_key(
        $taxonomies_map,
        array_flip($allowed)
    );
}, 10, 2);

### Example 2: Exclude a private taxonomy from indexing

If your site registers a taxonomy as public (because WordPress needs it for permalinks or templates) but you don't want its terms in search:

add_filter('queryra_indexable_taxonomies', function ($taxonomies_map, $post) {
    unset($taxonomies_map['internal_tag']);
    unset($taxonomies_map['admin_only']);
    return $taxonomies_map;
}, 10, 2);

### Example 3: Inject taxonomy-like data that isn't a real taxonomy

You can also use this filter to add taxonomy-shaped data from non-taxonomy sources — e.g. computed fields, external API data, or relational data from another table. Queryra treats the returned map as the source of truth; if you put it in the map, it gets indexed:

add_filter('queryra_indexable_taxonomies', function ($taxonomies_map, $post) {
    // Pull "recommended_for" from a custom relationship table
    global $wpdb;
    $rows = $wpdb->get_results($wpdb->prepare(
        "SELECT label FROM {$wpdb->prefix}book_recommendations WHERE book_id = %d",
        $post->ID
    ));
    if ($rows) {
        $labels = array_map(fn($r) => $r->label, $rows);
        $taxonomies_map['recommended_for'] = implode(', ', $labels);
    }
    return $taxonomies_map;
}, 10, 2);

The key recommended_for will be humanized as "Recommended For" and appended to the embedding text alongside the real taxonomies. It also gets a flat metadata entry (tax_recommended_for) for future filter use.

How the two filters fit together

The two filters cover different axes of the same record:

AxisFilterWhat it controls
Free-form text contentqueryra_indexable_meta_contentWhat appended to the description field before embedding. Best for paragraphs of text from custom field plugins.
Structured term dataqueryra_indexable_taxonomiesWhat goes into the structured taxonomies API field. Best for slug-based categorical data.

Use queryra_indexable_meta_content when you have unstructured text (Pods textareas, JetEngine wysiwyg, your own postmeta with paragraphs). Use queryra_indexable_taxonomies when you have categorical data that should also be filterable (book genres, materials, property types).

Both filters run during the same record-building pass — there's no ordering concern between them. Both are read on every sync of the affected post.

Stability commitment

Both filters are stable, official API surface:

  • Backwards-compatible: The signature ($content, $post_id) and ($taxonomies_map, $post) won't change. We may add new optional filters in future Queryra versions, but these two stay as documented.
  • No surprise removal: If we ever deprecate either filter, it gets a 6-month grace period with _doing_it_wrong() notices and migration docs.
  • No side effects: Filters run only during the sync flow. They don't fire during search-time, frontend rendering, or admin actions.
  • Performance: Each filter runs once per post on sync. Heavy logic inside the callback (database queries, API calls) adds to sync time — keep it light.

If you build production tooling on these filters and want a heads-up about future filter additions or related changes, email <a href="mailto:contact@queryra.com">contact@queryra.com</a> to be added to the developer announcement list.

TL;DR

  • queryra_indexable_meta_content($content, $post_id) — append text from any source to a record's indexable content. Use for Pods, JetEngine, custom postmeta with paragraphs of text, or anything that isn't on Queryra's native auto-extraction list.
  • queryra_indexable_taxonomies($taxonomies_map, $post) — override the auto-detected custom taxonomies. Use to whitelist a specific list, exclude private taxonomies, rename slugs, or inject taxonomy-shaped data from non-taxonomy sources.
  • Both filters are stable, non-breaking, and run only during sync. No frontend-side effects.
  • Add a add_filter() call in your theme's functions.php or a small custom plugin — no Queryra settings to toggle, the filters are always active.

For the deep dive on what Queryra indexes natively (page builders, custom fields, taxonomies), see Custom Taxonomies in AI Search.