benecaster_follower_signup()
benecaster_follower_signup( int $show_id, string $email, string $name = '', string $wall_name = '', string $password = '' ): array|WP_Error
Signs one email address up as a free follower of a show. This is the public entry point for custom signup surfaces — a popup overlay, a Gutenberg block, a WP-CLI command, a landing page posting to your own endpoint.
Everything the built-in [benecaster_follower_signup] shortcode does, this does: it provisions a WordPress user when the address is new, writes a follower token row, fires benecaster_token_generated (which sends the welcome email) and then benecaster_follower_signed_up. It is the same code path, so you inherit all of it without reimplementing any of it.
Idempotency is the whole value, and it is why the return is an array rather than an ID. Calling this twice for the same address and show is safe and is expected — a second call produces no second account, no second token and no second welcome email.
Follower signup is not license-gated. It works identically on the free WordPress.org plugin and on any paid plan. The only limit is the 100-follower cap on an unlicensed install, enforced at signup: at 100 the form stops accepting new followers and shows the podcaster an upgrade prompt. Existing followers are unaffected, and no follower is ever demoted to the public feed.
Handle the cap: this function returns a WP_Error with code benecaster_follower_cap_reached once an unlicensed show holds 100 followers. A refusal provisions nothing — no WordPress user, no token, no welcome email — so a caller that assumes an array return and reads $result['created'] will fatal on a WP_Error. Check is_wp_error( $result ) first. Existing followers are untouched by a refusal, and the same address can be submitted again successfully once the show is connected.
The cap is fixed. No filter or setting changes it.
Parameters
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
show_id |
int |
— | Yes | The show to follow. Must be a benecaster_show post. |
email |
string |
— | Yes | The follower's email address. |
name |
string |
'' |
No | Display name for a newly provisioned account. Blank leaves the account unnamed. |
wall_name |
string |
'' |
No | Supporter Wall display name, written to user meta. Truncated at 100 characters. Blank leaves any existing value untouched. |
password |
string |
'' |
No | For a brand-new account only, and must satisfy SignupPasswordPolicy. Silently ignored when the address already has an account — see the notes. |
Return Value
Type:
array|WP_Error
array{user_id: int, show_id: int, tier_slug: string, created: bool} on success. WP_Error for an invalid show (benecaster_follower_invalid_show: not a show, or a show that is not published — draft, scheduled, private or trashed), an invalid email address, a password failing policy on a new account, or a failed user creation.
Example
$result = benecaster_follower_signup(
$show_id,
sanitize_email( wp_unslash( $_POST['email'] ?? '' ) ),
sanitize_text_field( wp_unslash( $_POST['name'] ?? '' ) )
);
if ( is_wp_error( $result ) ) {
// Safe to show — the messages are deliberately non-enumerating.
wp_send_json_error( [ 'message' => $result->get_error_message() ], 400 );
}
wp_send_json_success( [
'message' => $result['created']
? __( 'Check your inbox for your private feed link.', 'my-addon' )
: __( "You're all set — we've sent your feed link again.", 'my-addon' ),
] );
Hooks Fired
Notes
created reports whether a WORDPRESS USER was created, not whether a token was — and the difference is a real signup, not an edge case. An address that already has an account on the site but no token for this show — a lapsed follower, or somebody who bought something else here — gets a token and a welcome email, and created is still false.
So created === false does not mean "nothing happened". If your UI needs "are you already following this show?", created alone will not answer it: check whether benecaster_follower_signed_up fired, or ask the token repository directly. The one case where genuinely nothing happens is an address that already holds a token for this show, and that returns created: false too. In that case tier_slug comes from the existing token, which may differ from what benecaster_follower_tier_slug would return today.
A password is ignored, silently, when the address already has an account, and both halves of that are deliberate. Applying it would be account takeover by email address alone. Erroring instead would turn a public form into an email-enumeration oracle — the success-on-repeat behaviour exists precisely to stop that, and refusing here would give away exactly what it protects. You cannot use this function to set a password.
Do not add your own "that email is taken" check in front of this call. You would reintroduce the enumeration leak the function is careful to avoid.
Do not resolve FollowerSignup from the container. The class is not part of the stable surface; this function is.
FollowerSignup::signup_new_only() is deliberately NOT wrapped and should not be. It exists for flows with nobody at a keyboard — a donation webhook, an import — and treats "user already exists" as terminal: no token, no follower conversion. Such a caller cannot know the person's current relationship to the show (paying subscriber, cancelled, existing follower) and must not override it. If an add-on needs that behaviour it gets its own function rather than a flag on this one. Do not use benecaster_follower_signup() to enroll somebody who is not at a keyboard.
Need this built rather than just documented? See our services →