Customizing Episode Listings
Benecaster’s episode-listing shortcodes — [benecaster_episodes], [benecaster_latest_episode], and [benecaster_related_episodes] — all share a common filter that lets you control how each item renders. A single callback covers all three surfaces.
Controlling what items render: benecaster_episode_item_output
The benecaster_episode_item_output filter fires once per rendered item across all three shortcodes. You receive the default HTML, the episode and show IDs, the current user’s tier slug, and whether the episode is locked for the current visitor. Return the HTML unchanged, return a replacement string, or return "" to suppress the item entirely.
add_filter( 'benecaster_episode_item_output', function ( string $html, int $episode_id, int $show_id, string $user_tier, bool $is_locked ): string {
// $html — the default rendered markup for this item
// $episode_id — post ID of the episode
// $show_id — post ID of the show
// $user_tier — the current user's active tier slug, or '' if not subscribed
// $is_locked — true when the user cannot access this episode
return $html;
}, 10, 5 );
Two common patterns, both written up as complete recipes:
- Hide locked episodes from all listing shortcodes — return an empty string for locked items and the slot is skipped entirely.
- Show a teaser card for locked episodes — return custom markup instead, so visitors can still discover the content.
One thing worth knowing before you reach for the first of those: [benecaster_episodes] also takes a show_locked="false" attribute, which runs before this filter and only affects that one shortcode instance. For a single list it is the cheaper option. The filter is the right choice when you want the same behaviour everywhere without repeating the attribute.
The $is_locked value reflects all access rules — including any rules registered by third-party code via benecaster_episode_is_accessible — so you don’t need to replicate access logic in this callback.
Customizing pagination output
When [benecaster_episodes paged="true"] is set, the shortcode renders a Previous / “Page N of M” / Next navigation strip below the list. Replace it entirely with the benecaster_episodes_pagination_output filter:
add_filter( 'benecaster_episodes_pagination_output', function ( string $html, \WP_Query $query, array $atts ): string {
$current = (int) ( $query->query_vars['paged'] ?? 1 );
$max = (int) $query->max_num_pages;
if ( $current >= $max ) {
return ''; // last page — no next link needed
}
$next_url = add_query_arg( 'ep_page', $current + 1 );
return sprintf(
'<div class="my-load-more"><a href="%s">Load more episodes</a></div>',
esc_url( $next_url )
);
}, 10, 3 );
The filter fires even on single-page results, so you can inject a custom strip unconditionally. Check $query->max_num_pages before building navigation to avoid rendering arrows that point nowhere.
Disambiguating multiple paged lists
When two [benecaster_episodes paged="true"] shortcodes appear on the same page, they both read ?ep_page=N by default — clicking Next on either list advances both simultaneously. Assign a unique query var per shortcode with benecaster_ep_page_query_var:
add_filter( 'benecaster_ep_page_query_var', function ( string $query_var, int $show_id, array $atts ): string {
return 'ep_page_' . $show_id;
}, 10, 3 );
The shortcode’s Previous/Next links are updated automatically to use the new var name. If you also use benecaster_episodes_pagination_output to build custom navigation, use the same overridden var name in add_query_arg().
Further reading
- Shortcodes Reference — all
[benecaster_episodes]attributes includingpaged - Template Overrides — override the episode list and episode page templates from your theme
- benecaster_episode_item_output — the full filter signature and parameter reference
- Recipes — complete, working examples built on these filters
See Also
Need this built rather than just documented? See our services →