Skip to main content

Import a follower list from code

Free Intermediate

Add a list of email addresses as free followers from an external system or your own code. Subscribers → Bulk enroll → Add as: Followers is the admin screen for this; these are the two programmatic routes to the same code. Use it for a mailing list, a Patreon export’s free members, or a newsletter you are folding into the show — anywhere you have addresses and want each one to get a follower feed.

From another system

Call the REST endpoint with an application password for an administrator. Leave out tier_slug — a follower is not a tier:

curl -X POST https://your-site.com/wp-json/benecaster/v1/shows/42/subscribers/bulk-enroll \
  -u 'admin-user:xxxx xxxx xxxx xxxx xxxx xxxx' \
  -H 'Content-Type: application/json' \
  -d '{"token_type":"follower","addresses":["ana@example.com","ben@example.com"]}'

The batch runs on the next WP-Cron tick; poll GET /shows/42/subscribers/bulk-enroll/status for the report. Up to 1,000 addresses per request.

In-process

From an add-on or a WP-CLI command in your own plugin, run it synchronously and read the report directly — see the code example.

An address that already has a token for the show is left exactly as it is — reported already_enrolled, not converted, not emailed. That includes paying subscribers: an import of your whole mailing list will not turn your paying members into followers. Do not try to “fix” a row by revoking and re-importing it; a revoked token still counts as having one.

Every new follower is sent a welcome email, even when the show’s welcome email is switched off — it is the only way a follower receives their feed URL (the plaintext token exists once, at generation). Warn whoever owns the list before you run it.

The 100-follower cap on an unlicensed install applies to imports too, and has no filter. Rows past it come back skipped with message: follower_cap_reached; handle that rather than looking for a way around it. On a connected show the cap does not apply.

Double opt-in is honoured. If a site returns true from benecaster_follower_double_optin, imported addresses are sent a confirmation email instead of a token, and the row reads created with message: confirmation_sent. $enrolled on benecaster_bulk_enrollment_complete counts them too — check $token_type (the action’s sixth argument) before treating $enrolled as new paying members.

token_type accepts only subscriber and follower; anything else is refused (400 over REST, InvalidArgumentException in-process).

Not at a keyboard and need someone added one at a time instead? See Build a custom follower signup UI.

Code

<?php
add_action( 'benecaster_boot', function ( \Benecaster\Container $container ): void {
    if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
        return;
    }

    \WP_CLI::add_command( 'my-addon import-followers', function ( array $args, array $assoc ) use ( $container ): void {
        $show_id   = absint( $assoc['show'] ?? 0 );
        $addresses = file( (string) ( $args[0] ?? '' ), FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ) ?: [];

        $report = $container
            ->make( \Benecaster\Membership\BulkEnrollmentProcessor::class )
            ->enroll( $addresses, $show_id, '', token_type: 'follower' );

        foreach ( $report['rows'] as $row ) {
            if ( 'follower_cap_reached' === ( $row['message'] ?? '' ) ) {
                \WP_CLI::warning( "{$row['email']}: follower limit reached — connect the show to add more." );
            }
        }

        \WP_CLI::success( sprintf( 'Added %d, already on the show %d, skipped %d, errors %d.',
            $report['enrolled'], $report['already_enrolled'], $report['skipped'], $report['errors'] ) );
    } );
} );

View on GitHub →

Hooks Used