Skip to main content

benecaster_send_broadcast()

Utilities Free
benecaster_send_broadcast( int $show_id, string|array $audiences, string $subject, string $html, ?string $preheader = null ): int

Sends one message you wrote to the listeners of one show, in one or more audiences, and returns the broadcast ID. Pass several audiences to reach several tiers at once: a listener in more than one is mailed once, under the one broadcast.

Each recipient goes through the same pipeline as every Benecaster email: the opt-out check (anyone who unsubscribed from announcements, or from everything, is skipped and logged as suppressed), the merge-tag and body filters, the List-Unsubscribe headers and the email log. The body is wrapped in the usual header, footer, unsubscribe link and business address.

It returns at once, and the recipients are queued in the background. The call works out who the audiences reach, records the broadcast and returns its ID before anyone is mailed. WP-Cron then hands the recipients to the email queue in batches of 100, on the benecaster_broadcast_send_batch event, checking each recipient’s opt-out as their batch runs, so a listener who unsubscribes part-way through is not mailed. A batch that is interrupted is picked up again without mailing anyone twice. That makes it safe to call from a web request whatever the size of the audience. Delivery follows later still, from the queue.

Parameters

Name Type Default Required Description
show_id int — Yes WordPress post ID of the show the broadcast is from. Not a show in the trash.
audiences string|array — Yes One audience slug, or a list of them: paying, followers, all, tier:SLUG, or a slug an add-on defines, as benecaster_find_audience_user_ids() takes them.
subject string — Yes Subject line. {{tags}} are filled in per recipient.
html string — Yes The message body, as HTML. {{tags}} such as {{subscriber_name}} are filled in per recipient and escaped.
preheader string|null null No The inbox preview line, or null for none.

Return Value

Type: int

The broadcast ID, returned before anyone has been mailed. 0 when the broadcast is refused: not a show (or a show in the trash), no audience, or an empty subject or body.

Example

$broadcast_id = benecaster_send_broadcast(
    $show_id,
    [ 'tier:gold', 'tier:silver' ],           // A listener in both is mailed once.
    __( 'Live show this Friday', 'my-addon' ),
    '<p>Hi {{subscriber_name}},</p><p>We record live on Friday at 8pm.</p>',
    __( 'Join us live on Friday', 'my-addon' ) // Inbox preview line, or null.
);
if ( 0 === $broadcast_id ) {
    // Refused: not a show, no audience, or an empty subject or body.
}

// Registered when your plugin loads, NOT next to the call above: the
// recipients are queued in the background, so this fires in a later
// WP-Cron request.
add_action( 'plugins_loaded', static function (): void {
    add_action( 'benecaster_after_broadcast_send', static function ( int $id, int $show_id, array $counts ): void {
        error_log( sprintf( 'Broadcast %d queued %d; %d had opted out.', $id, $counts['queued'], $counts['suppressed'] ) );
    }, 10, 3 );
} );

Hooks Fired

Notes

One call per message, not one per tier. Two calls are two broadcasts, and anyone in both tiers gets the message twice.

The recipient list is fixed when you call it. Someone who joins a tier afterwards is not added.

Listen for the finish where your plugin loads. benecaster_after_broadcast_send fires once, in the WP-Cron request that hands the last recipient to the queue, not in the request that made the call, so a listener added next to the call is gone by then. benecaster_before_broadcast_send fires in the calling request, once the broadcast is recorded and before anyone is sent. "Sent" means queued, as with every Benecaster email.

Progress is on the broadcast's record. Until the last batch it is listed as sending by the broadcasts REST route (GET /benecaster/v1/broadcasts), with its recipient count and its queued, suppressed and skipped figures rising batch by batch. A broadcast is recorded even when every recipient had opted out. If the show is trashed part-way through, the broadcast stops and the recipients not yet reached count as skipped.

Write {{tags}} into the body rather than filling them in yourself. Benecaster fills them per listener and escapes them.

Need this built rather than just documented? See our services →