benecaster_feed_request_dispatched
Fires after every feed-URL request is resolved, whatever the outcome — the token was valid, over its limit, revoked, or not found at all. All four states fire it, which is what makes it usable for monitoring rather than only for the success path. The payload is a single array describing the request.
Benecaster consumes it internally to write the feed request log, subject to the log-enabled and log-level settings — but it is designed as a public extension surface. Add-ons and site code can hook here for realtime feed-request notifications — for example, a Slack ping when a cancelled subscriber’s app is still polling, or an alerting layer on top of the built-in log.
token_id and token_prefix are null when token_status is not_found (no matching token row). Geo fields (country_code, region_code) are null when the site has no GeoIP database configured or the lookup returns no result.
over_limit_effect is always present and is the supported way to tell the two over-limit outcomes apart:
| over_limit_effect | HTTP | What the listener got | |—|—|—| | 'demoted' | 200 | The public feed. A paid token over the limit — the listener is still receiving episodes, just not the private ones. | | 'locked' | 410 | Nothing. A free token locked out under cap enforcement. | | null | — | token_status is not over_limit. |
A demotion and a lockout are not interchangeable, and treating them as one thing is why this key exists. One is a downgrade the listener may not even notice; the other is a listener who has stopped receiving your podcast. An alert that fires the same way for both is wrong for one of them.
token_status deliberately keeps its four values. Inventing a fifth would silently change what the nightly analytics rollup counts, because it aggregates over-limit requests as one cohort — which is correct for analytics and wrong for alerting. Separate key, not a new status value.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
$context |
array |
— | Request context array. Keys: `show_id` (int), `token_id` (?int — null on not_found), `token_prefix` (?string — first 8 chars of the plaintext token, null on not_found), `token_status` (string: 'valid' | 'over_limit' | 'revoked' | 'not_found' — `over_limit` covers BOTH outcomes; read `over_limit_effect` to tell them apart), `over_limit_effect` (?string: 'demoted' | 'locked' — always present, null unless `token_status` is `over_limit`), `ip_hash` (string — SHA-256 hash of the requester's IP using benecaster_ip_hash_salt), `user_agent` (string), `country_code` (?string — ISO 3166-1 alpha-2, null when GeoIP unavailable), `region_code` (?string — ISO 3166-2 region, null when GeoIP unavailable) |
Examples
Slack alert when a cancelled subscriber's app is still polling
add_action( 'benecaster_feed_request_dispatched', function ( array $ctx ): void {
if ( $ctx['token_status'] !== 'revoked' ) {
return;
}
wp_remote_post( MY_SLACK_WEBHOOK_URL, [
'body' => wp_json_encode( [
'text' => sprintf(
'Revoked token poll detected — show %d, prefix %s, country %s',
$ctx['show_id'],
$ctx['token_prefix'] ?? 'n/a',
$ctx['country_code'] ?? 'unknown'
),
] ),
] );
} );
Notes
The built-in feed request log already records the same data for all four token statuses, so hooking this action to re-implement the log gains you nothing. Its value is what the log cannot do for you: rate limiting, or alerting in real time. For rate limiting, compare the token_prefix or ip_hash field against your own counter store.
Use token_status for analytics, and over_limit_effect for what the listener actually received. The full reading: valid served the private feed; revoked / not_found served the public feed or a 403 depending on the show's own fallback setting; and over_limit served the public feed when over_limit_effect is 'demoted', or nothing at all when it is 'locked'.
Need this built rather than just documented? See our services →