October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Get URL Parameters in WordPress: Query Strings, Custom Variables, and REST APIs

A practical WordPress guide to reading query strings, registering custom query variables, handling REST parameters, building encoded URLs, escaping output, and fixing missing values.
Length10 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a URL such as https://example.com/offers/?campaign=spring&item=42, read ordinary query-string values from PHP’s $_GET. If the value is a WordPress front-end query variable, register its name with the query_vars filter and then call get_query_var(). In a REST endpoint, read parameters from the WP_REST_Request object. Sanitize and validate every value, construct links with add_query_arg(), and escape generated URLs with esc_url() when you output them.

What a URL parameter is in WordPress

A URL parameter is a key-value pair in the query string, the part after ?. In /offers/?campaign=spring&item=42, the keys are campaign and item; their values are spring and 42. Multiple pairs are separated by &. A URL can also contain path parameters, such as an endpoint route ending in /genres/rpg, while form submissions and REST requests can carry values in a request body or JSON payload.

As an Amazon Associate I earn from qualifying purchases.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

WordPress offers different access points because these values belong to different request layers. PHP receives the raw query string through superglobals. WordPress’s main query exposes only variables it knows about. REST callbacks receive a request object that combines route, query, body, and JSON data. Choosing the matching layer prevents the common problem of a value appearing in the browser but being empty in code.

Choose the right way to read a parameter

Situation Recommended API Registration needed? Typical use
Any ordinary query-string key $_GET, after unslashing, validation, and sanitization No A campaign code, filter, or one-off value handled by your own PHP
A value that should participate in WordPress’s main query get_query_var() Yes, for custom names through the query_vars filter Templates, conditional routing, and query-aware front-end features
A custom REST route WP_REST_Request methods such as get_param() Define route arguments for production validation and sanitization JSON clients, JavaScript applications, and integrations
Creating a link with parameters add_query_arg(), then output with esc_url() No Preserving an existing query string while adding or replacing keys

The important distinction is that get_query_var() is not a general replacement for $_GET. It reads values that WordPress has placed in WP_Query; an unregistered custom name normally returns its default instead.

Read a basic query parameter with $_GET

Use this pattern when your code simply needs a key from the current request:

$campaign = isset( $_GET['campaign'] )
    ? sanitize_text_field( wp_unslash( $_GET['campaign'] ) )
    : '';

wp_unslash() removes WordPress’s added slashes before sanitizing. sanitize_text_field() is suitable for a short text value, not every data type. If the key is absent, the example returns an empty string instead of generating a notice.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not treat sanitization as authorization. A sanitized user ID can still refer to another user, and a sanitized product ID can still be outside the current visitor’s permissions. Perform capability checks, ownership checks, nonce checks, or server-side business rules separately wherever the parameter controls access or an action.

Use type-specific validation

Match validation to the value’s contract before using it:

  • For an integer ID, convert and validate an integer, then verify that the object exists and the current user may access it.
  • For an allowlisted mode such as grid or list, compare against the fixed set and reject everything else.
  • For a date, require the format your application documents and reject impossible dates rather than silently changing them.
  • For an email address, use an email-specific validator instead of a generic text sanitizer.
  • For a URL, validate the scheme and host appropriate to your application; never assume a sanitized URL is safe to redirect to.

Read input once, normalize it, and pass the normalized variable through your application. Avoid printing $_GET directly into HTML, JavaScript, SQL, shell commands, or redirects.

Register a custom WordPress query variable

Use get_query_var() when the parameter is part of a normal front-end WordPress request and should be available through the main query. Register the name on the query_vars filter:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
add_filter( 'query_vars', function ( $vars ) {
    $vars[] = 'campaign';
    return $vars;
} );

$campaign = get_query_var( 'campaign', '' );

With that code active, a request such as /offers/?campaign=spring can be read with get_query_var( 'campaign', '' ). The second argument is the fallback returned when WordPress has no value.

The official get_query_var() reference documents this behavior: the function retrieves values from WP_Query and does not retrieve an arbitrary custom variable until that name is registered. Register the filter in a plugin or a theme’s appropriate bootstrap file so it runs before WordPress builds the main query.

When registration is not necessary

If a small piece of PHP only needs to inspect a query-string key and does not need the main query, reading $_GET is simpler. Registering every ad-hoc key can make the query-variable namespace harder to understand. Use a registered variable when templates, conditional tags, rewrite logic, or other query-aware code need the value consistently.

Query-variable timing

Call get_query_var() during a request in which WordPress has initialized the main query. Calling it too early, before the normal query setup, can produce an empty result even when the URL is correct. In a REST callback, do not use this front-end approach; use the request object described below.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read parameters in a WordPress REST API endpoint

REST callbacks receive a WP_REST_Request instance. Read a query, path, body, or JSON parameter through that object instead of relying on global superglobals:

function my_endpoint_callback( WP_REST_Request $request ) {
    $genre = $request->get_param( 'genre' );

    return rest_ensure_response( array(
        'genre' => $genre,
    ) );
}

get_param() looks up a parameter supplied to the request. The REST API also exposes methods for more specific sources, including query parameters, URL parameters, body parameters, and JSON parameters. The REST API Handbook’s Requests documentation explains those access patterns and the request object’s role.

Define route arguments for production endpoints

When registering a route, describe each argument with a type and validation and sanitization callbacks. A route definition makes the endpoint’s contract explicit and lets WordPress reject malformed requests before your business logic runs:

register_rest_route( 'my-plugin/v1', '/offers', array(
    'methods'  => WP_REST_Server::READABLE,
    'callback' => 'my_endpoint_callback',
    'args'     => array(
        'item' => array(
            'required'          => true,
            'validate_callback' => function ( $value ) {
                return is_numeric( $value ) && (int) $value > 0;
            },
            'sanitize_callback' => 'absint',
        ),
    ),
) );

The exact route, permission callback, and argument rules depend on your application. Add a permission_callback for protected data or actions; validation only checks shape and value, not whether the caller is allowed to perform an operation. Return a clear WP_Error when a request fails a business rule after validation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Query, path, body, and JSON values

  • Query: supplied after ?, such as /offers?genre=rpg.
  • Path: captured by a route pattern, such as a route with (?P<id>d+).
  • Body: form-encoded request data.
  • JSON: a JSON request body, normally sent with the appropriate content type.

Use the source-specific request methods when you need to distinguish where a value came from. If the same key can appear in several places, define a clear precedence rule rather than allowing accidental overrides.

Build URLs safely with add_query_arg()

Use add_query_arg() instead of manually concatenating ?, &, and encoded values. It can add parameters to a base URL or update an existing query string:

$url = add_query_arg(
    array(
        'campaign' => 'spring',
        'item'     => 42,
    ),
    home_url( '/offers/' )
);

echo '<a href="' . esc_url( $url ) . '">View offer</a>';

The add_query_arg() reference specifically warns: “Important: The return value of add_query_arg() is not escaped by default.” The function helps construct the URL; it does not make output safe for every context. Escape the completed URL where it is rendered, normally with esc_url() for an HTML link.

Existing query strings and encoding

Suppose the base URL is /offers/?page=2. Passing an array with campaign adds it without requiring you to decide manually whether to use ? or &. Let WordPress encode parameter values rather than placing raw spaces, ampersands, or non-ASCII characters into the string. Preserve the URL until output; do not decode and reassemble it unnecessarily.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a link that must retain only selected keys, construct a new URL from a trusted base and an explicit allowlist. Do not copy an entire untrusted query string into a redirect or HTML attribute.

Escape at the output context

Input handling and output escaping solve different problems. Sanitize and validate when data enters your application; escape immediately before sending it to a context such as HTML, an attribute, JavaScript, SQL, or a redirect. A value safe for one context may not be safe for another.

  • Use esc_url() for a generated URL printed in an HTML attribute.
  • Use esc_html() for a text value printed as visible HTML text.
  • Use context-appropriate WordPress escaping for JavaScript or other output contexts.
  • Use prepared database queries rather than inserting a parameter into SQL.

For example, this is unsafe because it prints raw input:

echo '<a href="' . $_GET['next'] . '">Continue</a>';

Build a trusted destination, validate any allowed target, and escape the final URL instead:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
$url = add_query_arg( 'campaign', $campaign, home_url( '/offers/' ) );
echo '<a href="' . esc_url( $url ) . '">Continue</a>';

Escaping does not make an arbitrary external redirect legitimate. If a parameter controls navigation, use an allowlist or a safe local-path policy before generating the link.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

End-to-end front-end example

The following pattern registers a variable, reads it, validates an allowlisted value, and displays it safely:

add_filter( 'query_vars', function ( $vars ) {
    $vars[] = 'view';
    return $vars;
} );

$view = get_query_var( 'view', '' );
$allowed_views = array( 'grid', 'list' );

if ( ! in_array( $view, $allowed_views, true ) ) {
    $view = 'grid';
}

$grid_url = add_query_arg( 'view', 'grid', home_url( '/offers/' ) );
$list_url = add_query_arg( 'view', 'list', home_url( '/offers/' ) );

printf(
    '<a href="%s">Grid</a> <a href="%s">List</a>',
    esc_url( $grid_url ),
    esc_url( $list_url )
);

The allowlist prevents an unexpected mode from reaching template logic. The URLs are generated by WordPress and escaped only when printed, which keeps construction and output responsibilities separate.

Why a parameter is empty: troubleshooting

1. Confirm the browser URL

Check that the complete request contains the expected key after ?, that pairs are separated by &, and that spelling and capitalization match the code. campaign and Campaign are different keys in your application. Check redirects in the browser’s network panel; a redirect may remove or replace the query string.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Match the API to the request type

If you are handling a normal page request, inspect $_GET or a registered get_query_var(). If the code runs inside a REST callback, inspect the supplied WP_REST_Request. A value sent as JSON will not necessarily appear in $_GET.

3. Verify custom-variable registration

For get_query_var(), confirm that the query_vars filter runs and appends the exact key. Confirm that the call occurs after WordPress has initialized the main query. If you do not need query integration, switch to a validated $_GET read instead.

4. Check encoding

Spaces, ampersands, plus signs, Unicode characters, and reserved URL characters must be encoded correctly. A literal ampersand inside a value can look like the separator between two parameters. Generate links with add_query_arg() and inspect the resulting URL rather than hand-building it.

5. Inspect rewrites, redirects, caches, and security layers

Permalink rules, reverse proxies, page caches, redirect rules, and security plugins can change a request before PHP sees it. Temporarily compare the failing URL with a direct request to a known working endpoint in a controlled development environment. Log normalized values server-side only while diagnosing; never expose raw input in the response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

6. Check Nginx query-string forwarding

WordPress’s REST API FAQ identifies an Nginx try_files configuration that fails to preserve arguments as one reason REST query parameters may not reach WordPress. The relevant pattern is:

try_files $uri $uri/ /index.php$is_args$args;

Apply server changes with your deployment process and test after reloading Nginx. The exact configuration must fit the rest of your site’s server block; do not paste a fragment blindly into production.

Testing checklist

  • Test a missing key and confirm your documented default is returned.
  • Test a valid value, an empty value, repeated keys, and an unexpected type.
  • Test encoded spaces, ampersands, Unicode, and reserved characters.
  • For IDs, test zero, negative numbers, very large numbers, and an ID the current user cannot access.
  • For REST routes, test query, path, body, and JSON input separately and verify validation errors.
  • Follow generated links and confirm that existing query parameters survive when they should.
  • Inspect the final rendered HTML to ensure URLs and visible values are escaped.
  • Test with caching, redirects, the production proxy, and the actual web server configuration enabled.

Practical decision guide

Start with the request boundary. For a simple page query, normalize $_GET. For a value that WordPress’s main query and templates should understand, register it and use get_query_var(). For a REST route, define arguments and read the WP_REST_Request. When creating a link, use add_query_arg(), then escape the finished URL at output. Keep validation, authorization, URL construction, and escaping as separate steps so a parameter cannot silently bypass one of them.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.