Classify tracking parameters and request headers

POM Cache uses query parameters and the HTTP Accept header to decide whether a request can share an HTML representation. These filters change request classification, so use them only for properties with a stable public meaning.

Add a tracking-only query parameter

Known tracking parameters can be removed from the cacheable request so marketing attribution does not create or bypass otherwise identical HTML.

add_filter(
    'pom_cache_tracking_parameters',
    static function ( $parameters ) {
        $parameters[] = 'campaign_source';

        return array_values( array_unique( $parameters ) );
    }
);

Adding campaign_source asserts that:

/offers/?campaign_source=newsletter

has exactly the same public representation as:

/offers/

Do not classify parameters that affect language, currency, price, search, pagination, filters, authentication, preview state, experiments, consent, or content. Non-tracking queries remain dynamic unless their owner explicitly registers a separate variant policy below.

Cache a finite content-changing query

Use pom_cache_query_variant when a route offers a small, known set of anonymous HTML representations. For example, a public catalog with a supported display mode can register:

add_filter(
    'pom_cache_query_variant',
    static function ( $policy, $query, $path ) {
        if ( '/catalog/' !== $path || ! isset( $query['view'] ) ) {
            return $policy;
        }

        return array(
            'namespace'  => 'catalog-display-v1',
            'parameters' => array( 'view' => array( 'grid', 'list' ) ),
            'max_age'    => HOUR_IN_SECONDS,
        );
    },
    10,
    3
);

This creates separate representations for ?view=grid and ?view=list; neither shares the query-free page. ?view=other and ?view=grid&currency=EUR remain dynamic. All values must be explicit strings. Do not use unrestricted search terms, tokens, emails or identifiers as variant values.

Register the policy before init and keep it stable for the request. Include a configuration identity in namespace when changing a connection or source would change the representation. Use ignore only for additional attribution parameters read by browser code, never for content or authorization. The filter receives raw decoded query values; its callback must validate any values it uses itself. POM Cache independently validates the returned allowlist.

The optional headers map accepts Cache-Control and X-Robots-Tag. These are sent on cached hits. Emit matching headers on live responses too. Registration explicitly authorizes origin storage; downstream browser or CDN caching remains controlled by those headers. This facility does not make a private or authenticated page safe to share.

Variants are read at wp_loaded, before the main WordPress query, and expire according to the file's generation time. After expiry, an error is returned dynamically rather than storing it or serving the expired file. Session, authentication, method and content-type exclusions still apply. Unclassified custom routes also need a narrowly scoped pom_cache_only_cache_known_pages decision after successful rendering; a variant policy alone does not classify them as a valid page.

Verify each representation separately, then parameter order, attribution, extra parameters, expiry, errors, authenticated requests and single-URL clearing. Do not change Apache rules to serve these variants directly: PHP enforces their policy and expiry.

Test canonicalization

For every added key:

  1. compare the response body with and without the parameter;
  2. repeat for all parameter values;
  3. confirm that no JavaScript bootstrap data changes;
  4. verify cookies, redirects, and headers;
  5. test the origin before a CDN;
  6. ensure analytics collection still works at the layer that owns it.

If the parameter can ever select different content, remove it from this filter.

Extend JSON-like Accept detection

POM Cache treats requests advertising JSON-like media types as non-HTML. The defaults are:

  • application/json;
  • application/activity+json;
  • application/ld+json.

Add another media fragment when a custom endpoint negotiates a non-HTML representation:

add_filter(
    'pom_cache_accept_headers',
    static function ( $media_types ) {
        $media_types[] = 'application/vnd.example.catalog+json';

        return array_values( array_unique( $media_types ) );
    }
);

This narrows HTML eligibility. Removing a default or returning an incomplete list is dangerous because a JSON response could then be handled as an HTML candidate.

Header matching details

POM Cache compares lowercase Accept content against the configured fragments. Register lowercase media values and do not include unrelated header syntax.

This filter controls HTML classification; it does not create a progressive JSON path, validate a JSON payload, or set CDN cache headers. Use the progressive JSON APIs for those responsibilities.

Timing and deployment

Request normalization can begin during the early drop-in phase. A callback registered by an ordinary plugin may influence WordPress-phase behavior without being available for every earliest cache check.

After changing either filter:

  • clear existing HTML artifacts whose canonicalization changed;
  • review copied Apache rules and CDN cache keys;
  • test clean and parameterized requests;
  • confirm that private or negotiated content cannot reuse an older HTML file.