Add custom merge tags to all emails
Custom merge tags registered via benecaster_email_merge_tags are available in all Benecaster emails. With the Email Editor add-on active, these tags are also available in the drag-and-drop template builder — the same registration code unlocks them in both contexts without any additional steps.
The filter fires once per recipient, so values can be the same for everyone or computed individually per subscriber. The examples below use a recurring “round table” show format as the scenario: a podcaster wants to include the title of their next upcoming round table episode in subscriber emails.
When to Use This
Use benecaster_email_merge_tags when you want to:
-
Surface content from your WordPress site in email templates — custom post types, options, ACF fields, anything
-
Add a value that’s the same in every email (next event title, current season, site-wide promotion)
-
Add a per-subscriber value that differs for each recipient (join date, tier name override, subscriber-specific URL)
-
Modify or override a built-in tag’s value for a specific show or use case
If your tag only makes sense in one email type — episode notifications, broadcasts, or welcome emails — use the type-specific variant instead of adding a check inside the shared filter.
Where to Put This Code
Your add_filter() call needs to run on every request where Benecaster sends email.
Recommended: a mu-plugin. Create a file at wp-content/mu-plugins/my-benecaster-customizations.php. It loads automatically on every request, survives theme changes, and cannot be accidentally deactivated.
Child theme functions.php works — Benecaster’s email pipeline fires after the theme loads, so the filter registers in time. One important caveat: if you ever switch themes — even swapping one child theme for another — the tags silently stop resolving. Sent emails will contain an empty string where the tag was, with no error logged. Fine for a site where the theme is locked in; risky for anything production-critical.
A site-specific plugin is a clean middle ground: decoupled from the theme, easy to deactivate deliberately.
The Three Shapes
The recipe works through the same scenario three ways.
A global tag, available in every email type. Hook benecaster_email_merge_tags, query for whatever you want to surface, and assign it into the tags array. The recipe’s {{next_round_table}} queries a roundtable custom post type for the earliest post with a future status. Use it in a template like any built-in tag:
The next round table is {{next_round_table}} — we'd love to see you there.
A type-specific tag. When the tag only makes sense in one email type, hook benecaster_email_merge_tags_{$type} instead — benecaster_email_merge_tags_episode_notification, say. It fires immediately after the shared filter, takes three parameters rather than four (the email type is dropped, since it’s implied), and saves you a check inside the callback.
A per-subscriber tag. The filter runs once per recipient, so the user ID lets you compute a different value for each one — a formatted join date, a personalized URL, a tier name override. For a 300-subscriber send the callback runs 300 times with a different user ID. Handle the null case: the user ID is null for admin-facing emails such as license alerts and feed health notices.
Notes
Always return a string. If there is no upcoming round table, return '' — an empty string is substituted silently. If you return null, false, or omit the key, the tag appears literally in the sent email.
The key is the tag name without braces. A key of next_round_table renders as {{next_round_table}}. No prefix, no namespace. Pick a name that won’t collide with a Benecaster built-in — check the merge tags reference for the reserved names.
The accepted-args count must match. The shared filter passes four arguments — tags, email type, user ID, show ID — so register it with 10, 4. Declare fewer and the missing parameters arrive as null. The type-specific variants pass three, so use 10, 3 there.
Cache across recipients when the value doesn’t change per subscriber. A site-wide value is identical for all 300 recipients in a send, but the filter still runs 300 times. Hold the result in a static variable so the query runs once per PHP request instead of once per email.
Episode notification tags already include episode context. For callbacks on benecaster_email_merge_tags_episode_notification, the tags array arrives with episode_id pre-populated with the WordPress post ID. You can pass that directly to get_post_meta(), get_the_title(), or any other post-based function without resolving the ID from a URL.
Related
-
Email Merge Tags Reference — full list of built-in tags and which email types they’re available in
-
Customizing Email Templates — template override and branding options
-
Default Email Templates — which emails Benecaster sends and when
Code
<?php
add_filter(
'benecaster_email_merge_tags',
function ( array $tags, string $type, int $user_id, int $show_id ): array {
$tags['show_manager_name'] = (string) get_post_meta( $show_id, '_my_addon_manager_name', true );
$tags['show_manager_email'] = (string) get_post_meta( $show_id, '_my_addon_manager_email', true );
$tags['episode_count'] = (string) wp_count_posts( 'benecaster_episode' )->publish;
return $tags;
},
10,
4
);
Hooks Used
Need this built rather than just documented? See our services →