[benecaster_tier_gate]
Shows its content to subscribers at or above a tier, and the content after [benecaster_else] to everyone else. The first enclosing shortcode in the plugin — every other Benecaster shortcode is self-closing.
[benecaster_tier_gate min_tier="growth"]
[benecaster_ai_search]
[benecaster_else]
[benecaster_search]
[/benecaster_tier_gate]
Only the taken branch is ever run. The raw content is split on the first [benecaster_else] (or [benecaster_else /]) before do_shortcode() runs on either half, so a shortcode in the hidden branch never executes — for [benecaster_ai_search] (billed per search on the podcaster’s own key), only the chosen tier ever gets a box that can spend it. This covers shortcodes only: a dynamic block placed between the tags is rendered by do_blocks() before any shortcode runs.
No [benecaster_else] means a visitor below the tier sees nothing, never the gated content. A stray [benecaster_else] outside a gate renders nothing.
Gates cannot be nested — WordPress’s parser cannot nest a tag inside itself, so an inner [/benecaster_tier_gate] closes the outer gate and the rest prints as literal text. Sequential gates are fine; for a compound condition use benecaster_tier_gate_passes.
Tier resolution goes through benecaster_get_user_tier_for_show(), so Preview as Tier applies. Logged-out visitors, visitors with no active token for the show, and followers take the else branch. An unknown min_tier fails closed to the else branch.
Ranking is “at or above” by position in the show’s tier list, later = higher — the same order Memberships → Tiers, the pricing table, and the audio-variant cascade use. When both the visitor’s slug and min_tier exist in built-in membership tiers, they’re ranked in that list; otherwise both are ranked in the tier map. The two are never mixed, and a slug found in neither fails closed. A built-in show’s tier rank is the order the podcaster sets on Memberships → Tiers — drag a tier by its handle, or use the arrow keys on a focused handle; new tiers are always added last. Position, never the raw stored value, is what’s compared: values were made explicit per show at db 1.57.0, but can still tie via the REST API, so ranking by position is what keeps a gate accurate regardless.
No licence check, deliberately — this is website gating, and Benecaster’s enforcement floor stops at content delivery. On an unlicensed install nobody holds a paid tier, so every visitor already takes the else branch regardless. Documented as min_plan: premium because subscriber tiers are a paid feature, not because the gate itself checks a licence.
Escaping: inner content is author-authored markup and is returned as written, like WordPress core’s own enclosing shortcodes — the editor’s save-time KSES is what applies. wpautop fragments (</p>, <p>, <br />) at the edges of each branch are trimmed.
In the RSS feed the gate resolves per compiled tier, not per listener. A gate in an episode’s Full Page Content or a show’s content passes through Benecaster\Feed\FeedTierGate before it reaches <content:encoded>, the item <description> (when Podcatcher Description is empty), the channel <description> and the channel <itunes:summary>. The feed cache is already per tier, so the tier being compiled picks the branch using the same ranking as the website, and the cache key is unchanged. The public feed, follower feeds, and buy-up pseudo-tier feeds always get the else branch — the gated branch never reaches them in any form. Differences from the website, all failing closed:
- Only the gate is resolved in the feed. Every other shortcode still arrives raw, and a
shortcode in the taken branch stays as literal text. benecaster_tier_gate_passesandbenecaster_tier_gate_outputdo not fire in the feed
— feeds are compiled and cached per tier, not per visitor.- A gate whose
show_idnames a different show takes the else branch. - A subscriber resolving to two or more slugs (two memberships, or a tier plus a buy-up)
can get the else branch on an item that reached them through a lower slug.
Never pass a buy-up’s token_type as min_tier. A buy-up holder resolves to their base tier slug, so a buy-up slug matches no tier and the gate stays shut for exactly the people who bought it. OR a buy-up in through benecaster_tier_gate_passes plus benecaster_user_has_buyup() instead — see the recipe Let buy-up holders through a tier gate.
Filters: benecaster_tier_gate_passes ( bool $passes, int $show_id, string $min_tier, string $user_tier ) — fires before either branch renders, website only; use it for conditions the attribute cannot express. benecaster_tier_gate_output ( string $output, bool $passes, int $show_id, array $atts ) — website only.
Parameters
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
min_tier |
string |
— | Yes | Internal tier slug required to see the gated content. The visitor passes when their tier ranks at or above it. Missing or unknown slug → else branch. |
show_id |
int |
current show
|
No | Show whose tiers are compared. Defaults to the current show/episode's show, then to the sole show on a single-show install. |
Example
<!-- AI search for Growth-tier subscribers and above, standard search for everyone else -->
[benecaster_tier_gate min_tier="growth"]
[benecaster_ai_search]
[benecaster_else]
[benecaster_search]
[/benecaster_tier_gate]
<!-- Gate a specific show's content on a multi-show install -->
[benecaster_tier_gate min_tier="premium" show_id="3"]
Thanks for being a premium subscriber!
[/benecaster_tier_gate]