What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
For a URL such as https://example.com/offers/?campaign=spring&item=42, PHP exposes the query-string values in $_GET. If the value is meant to participate in WordPress’s main query, register the name with the query_vars filter and read it with get_query_var(). Inside a REST API callback, use the WP_REST_Request object instead of reaching directly into superglobals.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
Whichever API you choose, treat the value as untrusted input: validate it for the expected type or allowlist, sanitize it for the destination, and escape a generated URL when you print it. The examples below cover front-end pages, custom query variables, REST routes, URL construction, and the common reasons a parameter appears to disappear.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
WordPress For Dummies (For Dummies (Computer/Tech)) | $16.59 | Buy on Amazon |
| 2 |
|
WordPress All-in-One For Dummies | $25.40 | Buy on Amazon |
| 3 |
|
Wordpress for Dummies | $26.94 | Buy on Amazon |
| 4 |
|
WordPress Web Design For Dummies | $16.48 | Buy on Amazon |
| 5 |
|
WordPress Web Design For Dummies | $29.30 | Buy on Amazon |
As an Amazon Associate I earn from qualifying purchases.
Choose the right WordPress API first
A query parameter is the part of a URL after the first question mark. In ?campaign=spring&item=42, the keys are campaign and item; their values are spring and 42. The same-looking URL can enter WordPress through different routing contexts, so the best reading method depends on what you are building.
| Situation | Read it with | Important condition |
|---|---|---|
| Ordinary PHP handling a front-end request | $_GET |
Check that the key exists, unslash the value, then validate and sanitize it. |
| A value that should be part of the WordPress main query | get_query_var() |
Register a custom name through the query_vars filter first. |
| A custom REST API route | WP_REST_Request |
Read query, path, body, or JSON parameters from the request object and define route arguments where possible. |
| Creating a link that carries parameters | add_query_arg() |
Build the URL with WordPress’s helper, then escape it at output because the helper does not escape automatically. |
Do not assume that get_query_var() is a safer spelling of $_GET. They serve different layers. WordPress’s reference notes that get_query_var() reads values recognized by WP_Query; an arbitrary custom key is not recognized until you register it.
#1 Best Overall
Read a basic query parameter with $_GET
Use this pattern when a normal page, template, shortcode, or plugin callback needs a value from the current URL:
$campaign = isset( $_GET['campaign'] )
? sanitize_text_field( wp_unslash( $_GET['campaign'] ) )
: '';
wp_unslash() removes the slashes WordPress adds to request data, and sanitize_text_field() removes or normalizes text that does not belong in a plain single-line string. The fallback makes the variable an empty string when the visitor did not supply campaign. Never print the raw superglobal directly into HTML.
Validate according to the value’s meaning
Sanitizing text is not enough when the application expects a number, date, email address, or one of a small set of choices. Validation answers whether the value is acceptable; sanitization prepares an accepted value for a particular use. Neither operation grants permission to view or change protected data.
$item_id = isset( $_GET['item'] )
? absint( wp_unslash( $_GET['item'] ) )
: 0;
$allowed_views = array( 'grid', 'list' );
$view = isset( $_GET['view'] )
? sanitize_key( wp_unslash( $_GET['view'] ) )
: 'grid';
if ( ! in_array( $view, $allowed_views, true ) ) {
$view = 'grid';
}
For an identifier, reject zero or an ID that the current user is not allowed to access before loading the record. For a date, parse the expected format and reject impossible dates rather than silently converting them. For an email, use an email-specific validator and still apply your application’s ownership or permission checks.
Understand repeated keys and arrays
A URL can contain a repeated key, such as ?tag=php&tag=wordpress, or an explicitly named array such as ?tag[]=php&tag[]=wordpress. PHP’s parsing behavior differs between those forms, so decide whether your endpoint accepts one value or a list. If a list is allowed, verify that the result is actually an array, sanitize every member, limit its length, and reject unexpected nesting.
$tags = isset( $_GET['tag'] ) ? wp_unslash( $_GET['tag'] ) : array();
$tags = is_array( $tags ) ? $tags : array( $tags );
$tags = array_map( 'sanitize_key', $tags );
$tags = array_slice( array_values( array_unique( $tags ) ), 0, 20 );
Do not use a query parameter as an authorization mechanism. A value such as user_id=17 is merely a request for a record; authorization must be checked against the logged-in user and the object’s capabilities.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteUse get_query_var() for a registered WordPress query variable
get_query_var() is appropriate when a custom value should be available through the main WordPress query, alongside built-in variables used by templates and conditional tags. Register the name before reading it:
Rank #2
add_filter( 'query_vars', function ( $vars ) {
$vars[] = 'campaign';
return $vars;
} );
$campaign = get_query_var( 'campaign', '' );
The official get_query_var() reference documents this behavior: the function retrieves variables from WP_Query, so an unregistered custom name returns the default rather than the URL value. Put the filter in code that loads on the request, such as a plugin or an always-loaded theme file. Registering the variable after the main query has already been parsed will not retroactively make the value part of that query.
Use a query variable in a template
Suppose the visitor opens /offers/?campaign=spring. After registering campaign, a template can read it and then apply the same validation rules used for $_GET:
$campaign = sanitize_key( get_query_var( 'campaign', '' ) );
$campaigns = array( 'spring', 'summer' );
if ( ! in_array( $campaign, $campaigns, true ) ) {
$campaign = '';
}
The second argument to get_query_var() is a default, not a validator. It prevents an undefined value from becoming a notice, but it does not constrain what a visitor can send. Keep custom names distinctive and avoid colliding with WordPress’s existing query variables.
When direct $_GET is the better choice
If the value is only an input to a small piece of PHP and does not need to influence the main query, using $_GET is simpler. Registering every temporary filter, sort, or tracking value as a query variable adds unnecessary coupling to WordPress’s routing layer. Choose get_query_var() when integration with the main query is the reason you need the parameter, not merely because it is available.
Read parameters in a WordPress REST API endpoint
REST callbacks receive a WP_REST_Request. Its methods expose values from the URL path, query string, form-encoded body, and JSON body. A minimal callback looks like this:
function my_endpoint_callback( WP_REST_Request $request ) {
$genre = $request->get_param( 'genre' );
return rest_ensure_response( array(
'genre' => $genre,
) );
}
The REST API handbook explains parameter access in its Requests documentation. Reading through the request object keeps the callback aligned with REST routing and avoids assumptions about which PHP superglobal contains the value.
Register route arguments with validation and sanitization
For a production endpoint, describe accepted arguments in the route definition. WordPress can run a validation callback before the main callback and a sanitization callback on accepted input:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #3
add_action( 'rest_api_init', function () {
register_rest_route( 'catalog/v1', '/books', array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'catalog_books_callback',
'args' => array(
'page' => array(
'default' => 1,
'sanitize_callback' => 'absint',
'validate_callback' => function ( $value ) {
return (int) $value > 0;
},
),
'genre' => array(
'sanitize_callback' => 'sanitize_key',
'validate_callback' => function ( $value ) {
return in_array( $value, array( 'history', 'science' ), true );
},
),
),
) );
} );
function catalog_books_callback( WP_REST_Request $request ) {
$page = $request->get_param( 'page' );
$genre = $request->get_param( 'genre' );
return rest_ensure_response( array(
'page' => $page,
'genre' => $genre,
) );
}
Use get_param() when the same name may come from more than one request source. Use a more specific request method when your contract requires one source, such as a path parameter or JSON body. Keep the route schema and callback expectations in agreement: a callback should not quietly accept a type or value that the route definition rejects.
Path, query, body, and JSON values
A route such as /catalog/v1/books/42 can define 42 as a path argument, while ?genre=science is a query argument. A POST request may carry form data or JSON in its body. The request object provides methods for these sources, so a callback can distinguish an identifier in the path from filters in the query and fields in the submitted document.
Do not echo a request value into a response merely because it was accepted. Enforce authentication, authorization, rate limits, and object-level permissions appropriate to the endpoint. Validation makes input well-formed; it does not make an operation safe for every caller.
Build parameterized URLs with add_query_arg()
When your code needs to create a link, use WordPress’s URL helper rather than manually concatenating question marks and ampersands:
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 →$url = add_query_arg(
array(
'campaign' => 'spring',
'item' => 42,
),
home_url( '/offers/' )
);
echo '<a href="' . esc_url( $url ) . '">View offer</a>';
add_query_arg() handles an existing query string and encodes values for the URL. It can accept an associative array, a single key and value, or a URL that already contains parameters. The helper does not decide whether the final URL is safe to print. WordPress states: Important: The return value of add_query_arg() is not escaped by default.
Escape at the output context
Escape the completed URL where it is rendered, as in esc_url( $url ) for an HTML link. Do not escape a URL early and then continue manipulating it as if it were raw data; repeated transformations can alter the value. If a URL is used in a different context, use the escaping function appropriate to that context.
| Approach | Existing query string | Encoding | Output safety |
|---|---|---|---|
| Manual concatenation | Easy to break by adding a second ? or losing an existing key |
You must encode each value correctly | You must still escape the final URL |
add_query_arg() |
Designed to add or replace query arguments | WordPress performs URL argument handling | Not escaped automatically; call esc_url() when printing |
Preserve or remove existing values deliberately
If the current URL already has a parameter, passing a new value with the same key replaces it. That is useful for pagination and filters, but it can also carry tracking or state values farther than intended. Build a fresh base URL when you want a clean link, and explicitly remove keys when your application should not preserve them.
Rank #4
Why get_query_var() is empty
An empty result is usually a routing or registration issue rather than a PHP failure. Work through these checks in order.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Inspect the complete URL. Confirm that the parameter appears after
?, that additional parameters use&, and that the spelling and capitalization exactly match the key your code reads. - Confirm registration. A custom name read with
get_query_var()must be added through thequery_varsfilter. Verify that the filter is loaded for this request and that the variable is not being removed by another filter. - Check request timing. Read the query variable after WordPress has initialized the main query. Code that runs before query parsing may not see the final value.
- Use the matching API. A REST callback should read from
WP_REST_Request; a value needed only by a PHP template can be read from$_GETafter validation. - Test encoding. Spaces, ampersands, plus signs, percent-encoded characters, and non-ASCII text can change how a server parses the value. Generate test links with
add_query_arg()instead of hand-building them. - Check redirects and caches. A canonical redirect, page cache, reverse proxy, security plugin, or application redirect may remove or rewrite a query string before your code runs. Compare the browser’s final URL with the original link and test an uncached request in development.
- Review rewrite and permalink settings. Flush permalinks only when you have changed rewrite rules; repeatedly flushing on every request is unnecessary and can hurt performance.
For temporary development diagnostics, log the validated shape of a value rather than dumping the whole request. Never print raw input into the page or leave sensitive request data in production logs.
When REST query parameters never reach WordPress
Sometimes the callback is correct but the web server routes the request incorrectly. WordPress’s REST API FAQ identifies Nginx try_files configuration as one cause of query parameters not reaching WordPress. The fallback must preserve the original arguments; the documented pattern is:
try_files $uri $uri/ /index.php$is_args$args;
The exact Nginx configuration belongs in the server block for the site, and changes should be tested and reloaded according to your hosting setup. The significant part is $is_args$args, which carries the query string when one exists. If the server instead falls back to /index.php without the arguments, WordPress receives the route but not values such as ?genre=science.
Also check proxy rules, redirects that normalize URLs, and security layers that reject or strip unusual keys. Compare a direct request to the origin with the public URL only in a controlled environment; do not bypass production security controls for a quick test.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesValidation, sanitization, and escaping checklist
- Presence: Decide whether the parameter is optional. Supply a safe default or return a clear error when it is required.
- Type: Convert integers with an integer-specific function, validate dates against the format you document, and reject values outside sensible bounds.
- Allowlist: For modes, sort orders, campaigns, and status values, accept only the documented choices.
- Structure: If arrays are supported, validate every element and cap the number and size of elements.
- Authorization: Check the current user’s capability and the target object’s ownership. A valid parameter is not proof that the caller may use it.
- Output: Escape for the destination context. Use
esc_url()for a generated HTML URL and the appropriate escaping function for text, attributes, JavaScript, or SQL contexts. - Privacy: Do not place passwords, access tokens, personal records, or other secrets in query strings. URLs can appear in browser history, server logs, analytics, referrers, screenshots, and caches.
- Observability: Log only what you need for diagnosis, remove sensitive values, and disable verbose request logging after development.
Complete front-end example
The following pattern registers a campaign variable, validates it, and creates a link to another offer while preserving safe URL handling:
add_filter( 'query_vars', function ( $vars ) {
$vars[] = 'campaign';
return $vars;
} );
function current_campaign() {
$campaign = sanitize_key( get_query_var( 'campaign', '' ) );
$allowed = array( 'spring', 'summer' );
return in_array( $campaign, $allowed, true ) ? $campaign : '';
}
$campaign = current_campaign();
$offer_url = add_query_arg(
array(
'campaign' => $campaign,
'item' => 42,
),
home_url( '/offers/' )
);
if ( $campaign ) {
echo '<a href="' . esc_url( $offer_url ) . '">View campaign offer</a>';
}
The allowlist prevents arbitrary campaign names from changing the page’s behavior. The link is generated from a known site URL, and escaping happens only when the final value is inserted into the href attribute.
Best Value
Testing parameter handling
Test each route with absent, valid, invalid, repeated, encoded, and unexpectedly large values. A small matrix catches more defects than testing only the happy path:
| Case | Example | Expected behavior |
|---|---|---|
| Missing optional value | /offers/ |
Use the documented default. |
| Valid scalar | ?item=42 |
Convert and accept the integer after authorization. |
| Invalid type | ?item=abc |
Reject it or return the safe invalid-value behavior; do not query an unintended record. |
| Encoded text | ?campaign=spring%20sale |
Decode, then apply the correct validation and sanitization rules. |
| Unexpected list | ?item[]=1&item[]=2 |
Reject it when a scalar is required, or process it under an explicit array contract. |
| REST body and query together | ?page=2 with a JSON body |
Read each field from the intended request source and apply route validation. |
For a REST endpoint, verify the HTTP status, response shape, and error message as well as the returned value. For a front-end page, inspect the final rendered link and confirm that the browser preserves the intended encoding. Include tests behind redirects and with the site’s normal cache and proxy path, because a request that works at the origin can still fail at the public URL.
Practical decision guide
- Is this a normal page request and you only need one input? Read
$_GET, unslash it, validate it, and sanitize it for use. - Should the value participate in WordPress’s main query? Register the key with
query_vars, then callget_query_var()after query initialization. - Are you inside a REST callback? Define route arguments and read values from
WP_REST_Request. - Are you generating a link? Use
add_query_arg()with a known base URL and callesc_url()at output. - Does the value vanish only in production? Inspect redirects, caches, proxies, security filters, rewrite settings, and the web server’s argument-preserving fallback.
These choices keep URL parsing, WordPress routing, REST contracts, and HTML output in their proper layers. The result is code that behaves predictably for ordinary links, custom query variables, and API clients without treating untrusted URL data as trusted application state.
Frequently Asked Questions
Are URL parameter names case-sensitive in WordPress?
Yes. Treat parameter names as exact identifiers and use one documented spelling and capitalization everywhere. A link using Campaign will not reliably match code reading campaign.
Can a URL fragment be read with $_GET?
No. The portion after # is handled by the browser and is not sent in the HTTP request. Use a query parameter or send the value through client-side code if the server must receive it.
Should I put an authentication token in a query string?
No. Query strings can be retained in browser history, logs, analytics, referrers, and caches. Use the authentication mechanism defined by your application or API, and keep authorization checks separate from parameter validation.
Quick Recap
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.




