Enumerate WP User IDs Eligible for a Broadcast Audience
Resolving “who would this broadcast go to?” into a concrete list of WordPress user IDs is the starting point for a custom send — your own email queue, an ESP API call, an export sheet, a dry-run count before anyone presses Send.
benecaster_find_audience_user_ids( $show_id, $audience ) is the way in. It needs nothing but WordPress and Benecaster loaded — no service container, no class import — so it works from a theme template, a snippet plugin, a WP-CLI command in another plugin, or an add-on.
Four audiences are built in:
| Audience | Who it reaches |
|---|---|
paying |
Paying subscribers only. Excludes followers and bridge members on a free tier |
followers |
Direct followers only |
all |
Every active token holder for the show |
tier:SLUG |
Active token holders on one tier, e.g. tier:gold |
The result is a deduplicated list of user IDs, in no guaranteed order.
The tier slug must match a configured tier exactly, and the match is case-sensitive. tier:Gold does not find gold. An unconfigured or wrong-cased slug resolves to an empty list rather than erroring, so a typo looks exactly like a tier nobody has joined.
tier:follower does not reach your followers. Follower tokens carry the slug follower, which is not a tier-map row on a normal install, so it resolves empty. Use the followers audience.
Custom audiences go through the filter. An unknown slug arrives as an empty array, so a callback can define one completely rather than filtering something core guessed at. The example below builds a temporal segment — everyone who joined in the last 30 days — for a “welcome, here is what you missed” send. That is a question core does not answer, which is what makes it worth writing.
Code
<?php
// Built-in audiences — including per-tier, which needs no callback.
$paying = benecaster_find_audience_user_ids( $show_id, 'paying' );
$gold = benecaster_find_audience_user_ids( $show_id, 'tier:gold' );
foreach ( $gold as $user_id ) {
$user = get_userdata( $user_id );
// Hand off to the email queue, an ESP API call, an export sheet, etc.
}
// A genuinely custom audience: everyone who joined in the last 30 days.
add_filter( 'benecaster_broadcast_audience_user_ids', function (
array $user_ids,
string $audience,
int $show_id
): array {
// Guard first. Without this you rewrite every audience at once.
if ( 'joined-last-30-days' !== $audience ) {
return $user_ids;
}
global $wpdb;
// created_at is stored in the site's timezone, so build the cutoff in
// the same timezone rather than in UTC — an install in UTC+13 would
// otherwise silently move the window by half a day.
$cutoff = wp_date( 'Y-m-d H:i:s', time() - 30 * DAY_IN_SECONDS );
$rows = $wpdb->get_col( $wpdb->prepare(
"SELECT DISTINCT user_id FROM {$wpdb->prefix}benecaster_tokens
WHERE show_id = %d AND status = 'active' AND created_at >= %s",
$show_id,
$cutoff
) );
return array_map( 'intval', (array) $rows );
}, 10, 3 );
Hooks Used
Need this built rather than just documented? See our services →