WordPress Query Vars allow you to pass custom data through your URLs safely. Learn how to register and access these parameters without breaking your site.
Last week, a client asked me to build a simple filtering system for their events page. They wanted the URL to look like example.com/events/?location=seattle, and they wanted the page to automatically update based on that parameter. I immediately reached for global $_GET variables, but I stopped myself. Using raw superglobals in WordPress is a shortcut to security headaches and potential conflicts with the WordPress Rewrite API: How URL Requests Map to Content.
Instead, I used WordPress Query Vars. They provide a standardized, secure way to handle URL parameters that plays nicely with the core routing engine.
At its core, the WordPress query system parses every URL to determine what content to display. When you visit a page, WordPress looks at the URL and figures out which post, category, or author it needs to fetch.
By default, WordPress only recognizes a specific set of parameters, like p, page_id, or s for search. If you try to pass ?location=seattle without registering it, WordPress simply ignores it. It doesn't know what to do with that key, so it effectively discards it during the main query parsing process.
To make WordPress acknowledge your custom data, you need to hook into the query_vars filter. This adds your variable to the "whitelist" of parameters the system is allowed to recognize.
Here is the code I dropped into my functions.php file:
PHPadd_filter( 'query_vars', 'register_my_custom_query_vars' ); function register_my_custom_query_vars( $vars ) { $vars[] = 'location'; return $vars; }
That’s it. Now, whenever a request hits the site, WordPress checks if location is present in the URL. If it is, it saves the value so you can access it later.
Once registered, you don't need to touch $_GET anymore. You should use get_query_var(), which is the safe, native way to retrieve your data.
I usually access it inside the pre_get_posts hook. This is the most efficient spot because it allows you to modify the WP_Query Explained: How WordPress Fetches Your Content object before the database query actually runs.
PHPadd_action( 'pre_get_posts', 'filter_events_by_location' ); function filter_events_by_location( $query ) { if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'event' ) ) { $location = get_query_var( 'location' ); if ( ! empty( $location ) ) { $query->set( 'meta_key', 'event_location' ); $query->set( 'meta_value', sanitize_text_field( $location ) ); } } }
You might be wondering why we go through this registration process instead of just using $_GET['location'].
I learned this the hard way early in my career. If you use $_GET directly, you bypass the WordPress abstraction layer. You end up with code that is harder to debug, prone to SQL injection if you aren't careful, and completely invisible to other plugins that might need to modify the query. Using get_query_var() ensures that your data is handled consistently with the rest of the WordPress ecosystem.
Always sanitize your input. Even though get_query_var() is safer than a raw superglobal, you are still dealing with user-supplied data. In my example above, I used sanitize_text_field() before passing the value into the query.
Also, remember that registering too many variables can technically bloat the global $wp_query object, though for most sites, the impact is negligible. Keep your registrations specific to the features you’re actually building.
Do I need to flush rewrite rules after adding a query var?
No. Adding a variable to the query_vars filter does not change your URL structure or rewrite rules, so you don't need to visit the Permalinks settings page.
Can I use these for REST API endpoints? Not directly. If you are building a decoupled frontend, you should look into Extending the WordPress REST API with Custom Endpoints instead of relying on standard query vars.
What happens if the user types a value that isn't in my database?
That depends on your pre_get_posts logic. If your query returns no results, WordPress will naturally show your theme's "no posts found" template.
Using WordPress Query Vars is a clean, professional way to handle dynamic content filtering. It keeps your code organized and ensures your custom parameters are treated as first-class citizens by the core.
Next time, I might experiment with mapping these variables to custom rewrite rules to get cleaner URLs like example.com/events/location/seattle, but for now, this query-based approach handles the job perfectly. If you're just starting out, stick to this method until you absolutely need the complexity of custom rewrite rules.
Master WordPress performance monitoring using OpenTelemetry. Learn how to implement distributed tracing for your REST API to find and fix hidden bottlenecks.