benecaster_feed_enclosure_url
Filters the audio or video URL placed in the RSS enclosure tag for each episode. Use to route downloads through a custom proxy, or append tracking parameters where you need $show_id. Fires after benecaster_episode_audio_url — prefer that hook for URL substitution; use this one for proxy-routing or parameter-appending.
Benecaster registers two callbacks at priority 10. Analytics\ProxyUrlRewriter swaps in the download proxy (/benecaster-download/{id}/?token={TOKEN}) on non-public tiers when download tracking is on for the episode. Feed\EnclosureUrlPrefixer joins the show’s Enclosure URL prefix (Show Settings → Feeds), dropping the URL’s leading https:// and keeping http://, and passes an already-proxied URL through untouched. Their result does not depend on which runs first: if the prefixer runs first, the rewriter replaces the prefixed URL wholesale with the proxy URL; if the rewriter runs first, the prefixer recognises the result as a proxy URL and leaves it alone. A callback registered at priority > 10 sees the final URL — prefixed, proxied, or both in whichever combination Benecaster produced.
Never wrap a proxy URL in a third-party prefix. Its ?token={TOKEN} is the subscriber’s private-feed credential; wrapping it would put that token in the tracking service’s own logs. Check for home_url( '/benecaster-download/' ) before prefixing, the way Benecaster’s own prefixer does.
The same value is also accessible through benecaster_feed_episode_data as the enclosure_url key — use this dedicated filter when you only need the URL and want to avoid receiving the full episode data array. The returned URL must always be a valid, non-empty URL.
It fires in two places, not one. Per item, where the result goes into enclosure url="..."; and again when building each channel-level <podcast:trailer>, with that trailer episode’s ID. Both of Benecaster’s own callbacks run in both places.
Two practical consequences. A prefix or proxy sees the trailer URL rewritten too, which is usually what you want. And a callback that counts its own invocations fires once per item plus once per trailer, not once per item.
For routing every enclosure through a measurement or CDN prefix service (Podtrac, OP3, Podscribe), use Show Settings → Feeds → Enclosure URL prefix instead of this filter — no code needed for that case.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
$url |
string |
— | The enclosure URL |
$episode_id |
int |
— | ID of the episode |
$show_id |
int |
— | ID of the show |
$tier_slug |
string |
— | Tier slug for this feed compilation pass |
Returns:
string
Examples
Append UTM source parameter to track feed traffic
add_filter( 'benecaster_feed_enclosure_url', function ( string $url, int $episode_id, int $show_id, string $tier_slug ): string {
if ( str_starts_with( $url, home_url( '/benecaster-download/' ) ) ) {
return $url;
}
return add_query_arg( 'utm_source', 'rss_feed', $url );
}, 10, 4 );
Serve preview audio URL for free tier
add_filter( 'benecaster_feed_enclosure_url', function ( string $url, int $episode_id, int $show_id, string $tier_slug ): string {
if ( 'free' === $tier_slug ) {
$preview_url = get_post_meta( $episode_id, '_preview_audio_url', true );
if ( $preview_url ) {
return $preview_url;
}
}
return $url;
}, 10, 4 );
Notes
The returned URL is placed directly in enclosure url="...". An invalid or empty return value produces a malformed feed item that podcast apps may reject.
Need this built rather than just documented? See our services →