What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
WordPress can narrow search results with the existing WP_Query system. Use tax_query for registered taxonomies such as categories, meta_query for custom-field values, and ordinary search arguments for keywords and post types. Add a custom URL filter only after registering it with query_vars; for REST searches, modify arguments through the endpoint’s documented hooks and parameters.
Choose the data model before writing the form
List every control visitors need and identify where each value is stored:
- Keyword: the normal
ssearch argument. - Content type:
post_type, such as posts, pages, or a registered custom post type. - Categories, tags, or custom taxonomies: registered terms passed through
tax_query. - Custom-field values: metadata passed through
meta_query.
WP_Query documents the available search, taxonomy, and metadata arguments, while WP_Meta_Query documents metadata comparisons and boolean relationships. Do not model a custom field as a taxonomy unless the value is actually registered as a term.
References: WP_Query and WP_Meta_Query.
Build a GET search form
A GET form keeps filters visible in the URL, making filtered result pages linkable and bookmarkable. Use field names that map directly to the values your query-building code expects.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
<form role="search" method="get" action="<?php echo esc_url( home_url( '/' ) ); ?>">
<label>
Keyword
<input type="search" name="s" value="<?php echo esc_attr( get_search_query() ); ?>">
</label>
<label>
Category
<select name="topic">
<option value="">Any topic</option>
<?php
$terms = get_terms( array( 'taxonomy' => 'topic', 'hide_empty' => true ) );
foreach ( $terms as $term ) : ?>
<option value="<?php echo esc_attr( $term->slug ); ?>">
<?php echo esc_html( $term->name ); ?>
</option>
<?php endforeach; ?>
</select>
</label>
<label>
Content type
<select name="post_type">
<option value="post">Articles</option>
<option value="product">Products</option>
</select>
</label>
<button type="submit">Search</button>
</form>
The get_search_form() reference shows how WordPress search forms can include additional controls; its example uses a hidden post_type field to constrain the content being searched. Escape values when outputting them, and preserve selected values when rendering the results page.
Filter by a taxonomy with tax_query
Taxonomy filters match terms from a registered taxonomy. Read the submitted slug, validate it against the taxonomy, and add a taxonomy clause only when a term was selected.
Rank #2
<?php
$search_args = array(
's' => isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '',
'post_type' => isset( $_GET['post_type'] ) ? sanitize_key( $_GET['post_type'] ) : 'post',
);
$topic = isset( $_GET['topic'] ) ? sanitize_title( wp_unslash( $_GET['topic'] ) ) : '';
if ( $topic && term_exists( $topic, 'topic' ) ) {
$search_args['tax_query'] = array(
array(
'taxonomy' => 'topic',
'field' => 'slug',
'terms' => $topic,
),
);
}
$query = new WP_Query( $search_args );
For several taxonomy facets, put multiple clauses in tax_query and set its relation to AND when every selected condition must match, or OR when any condition may match. The exact fields depend on your taxonomy registration and the values submitted by the form.
Filter by custom fields with meta_query
Metadata filters use a different structure. Each clause names the metadata key, supplies a value, and optionally specifies a comparison operator and data type.
Rank #3
<?php
$search_args['meta_query'] = array(
'relation' => 'AND',
array(
'key' => 'price',
'value' => 100,
'type' => 'NUMERIC',
'compare' => '>=',
),
array(
'key' => 'availability',
'value' => 'in_stock',
'compare' => '=',
),
);
Use NUMERIC, DATE, or another appropriate type when comparing stored values; otherwise a textual comparison can produce surprising ordering or ranges. For a single optional field, build the clause conditionally rather than adding an empty value. See the WP_Meta_Query reference for supported comparisons and nested relationships.
Register custom URL variables before reading them
WordPress does not expose every query-string key through get_query_var(). Register a public variable with the query_vars filter, then retrieve and validate it before adding it to a query.
Rank #4
<?php
add_filter( 'query_vars', function ( $vars ) {
$vars[] = 'audience';
return $vars;
} );
$audience = get_query_var( 'audience' );
$allowed = array( 'beginner', 'advanced' );
if ( ! in_array( $audience, $allowed, true ) ) {
$audience = '';
}
if ( $audience ) {
$search_args['meta_query'][] = array(
'key' => 'audience',
'value' => $audience,
'compare' => '=',
);
}
The registration and retrieval relationship is documented by query_vars and get_query_var(). A request value is untrusted: constrain it to known slugs, IDs, or ranges before using it in query arguments.
Use the main search request or a custom results page
You can apply these arguments when constructing a dedicated WP_Query, or alter the main search request with an appropriate WordPress hook and conditional checks such as is_search(). A dedicated query gives you more predictable control over pagination and output; modifying the main query lets themes and existing search templates continue to work. Whichever route you choose, keep the form field names, validation rules, and query arguments consistent.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
Handle filters in the REST API
REST searches are governed by the endpoint you call, not by the browser form alone. First inspect that endpoint’s documented collection parameters and permission rules. The REST API handbook notes that filtering behavior and authorization depend on the endpoint and the arguments registered for it: REST API Requests.
For WordPress post search requests, rest_post_search_query is the documented filter for adding or changing query arguments:
<?php
add_filter( 'rest_post_search_query', function ( $args, $request ) {
$topic = $request->get_param( 'topic' );
if ( is_string( $topic ) && $topic && term_exists( $topic, 'topic' ) ) {
$args['tax_query'] = array(
array(
'taxonomy' => 'topic',
'field' => 'slug',
'terms' => sanitize_title( $topic ),
),
);
}
return $args;
}, 10, 2 );
Read the hook’s current reference for the exact callback context: rest_post_search_query. Do not assume that an arbitrary query variable, taxonomy, metadata key, or authenticated-only filter is available on every REST endpoint.
Custom code or a plugin?
| Approach | Best fit | Trade-offs to check |
|---|---|---|
Custom PHP using WP_Query |
A known content model, bespoke form, or strict control over markup and query logic | Requires development, validation, accessibility work, pagination handling, and maintenance as WordPress changes |
| Search/filter plugin | A configuration-led interface with several facets and less custom code | Verify its current taxonomy, metadata, post-type, REST, theme, caching, performance, and WordPress-version support before adopting it |
Choose the option that matches your data model and maintenance capacity. A plugin is not automatically better for custom fields, and custom code is not automatically faster; the useful distinction is whether you can keep the filter definitions, query behavior, and front-end controls synchronized.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesQuick Recap
Troubleshoot filters that appear to do nothing
- Taxonomy returns no results: confirm the taxonomy name, term slug, post-type registration, and whether the term is actually assigned.
- Metadata range is wrong: check how values are stored and set an explicit
typesuch asNUMERIC. get_query_var()is empty: register the key withquery_vars; a raw$_GETkey is not automatically a public query variable.- The URL changes but results do not: inspect the generated query arguments and ensure the search template uses that query rather than discarding it.
- REST filtering fails: confirm the endpoint, parameter name, authentication requirements, and whether the endpoint exposes the hook or argument you are relying on.
- Pagination loses filters: carry the active query-string values into pagination links and sanitize them again when rebuilding URLs.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




