Onboarding Scenarios
A funnel is a short list of gates. The question for your site is which gates, and the honest answer depends on what the module enforces out of the box versus what it merely hosts. This page walks three builds, then covers the one piece of code that turns a pass-through page into a required step.
The builds
Minimum: password only
The funnel that ships enabled. One page, one shortcode:
[memb_set_password redirect_to="/welcome/"]
The member sets a password, the gate completes, the sandbox lifts. For a simple site with one product and no agreements to collect, this is enough, and it is the only build where every step is enforced with no code.
Recommended: password plus agreement and orientation
Add two pages to the funnel: an agreement (membership terms, code of conduct, refund policy) and a short welcome video or orientation page. Build the agreement as a Form Builder form, list both pages under Additional Funnel Pages in the module settings, and the funnel becomes a three-step journey: password, agreement, orientation.
Two things to know about this build:
- The agreement page is enforced only if you wire it as a custom gate (recipe below). Without that, it is a pass-through page: the member can finish the funnel without submitting, and the module will not stop them.
- The welcome video needs no gate at all. Most sites want it seen, not forced; leave it as a pass-through page and put the redirect there, so finishing setup lands the member on it.
High-security: password plus a second factor
For sites where member accounts hold money or personal data, add a two-factor step. Put [memb_totp_setup] or the passkey enrollment form on an extra page and add the page to the funnel. The module anticipates this: TOTP and passkey endpoints are automatically allowed inside the sandbox, so the enrollment flows work for a member who is still locked in.
Same enforcement caveat: the enrollment page is pass-through unless you register it as a gate. A pass-through 2FA page still gets most of the value, since the member is standing on the setup page with nothing else to do, but a site with a compliance requirement should enforce it.
What enforcement means here
Only the password gate is enforced out of the box. When a member finishes the password form, the module records the completion, checks every registered gate, and releases the member only when all of them pass. Every other page in the funnel is a page the member can visit, not a hurdle they must clear.
That is the right default: an agreement you force on people is an agreement a lawyer should review, and a video you force people to watch is a video they will mute. But when a step must be required, the gate system is public API and the recipe is short.
Making a form submission count as a gate
Gates are registered through the wpal/torii/onboarding/gates filter. A gate is four things: a label, a usermeta key for the completion flag, a callable that checks whether the gate is done, and the shortcode that renders it. The Form Builder fires wpal/torii/form_builder/submission/complete on every successful submission. Wire the two together and an agreement form becomes a real gate:
add_filter( 'wpal/torii/onboarding/gates', function ( array $gates ): array {
$gates['agreement'] = [
'label' => 'Sign the membership agreement',
'usermeta_key' => '_my_agreement_signed',
'is_complete' => function ( int $user_id ): bool {
return (bool) get_user_meta( $user_id, '_my_agreement_signed', true );
},
'render' => 'memb_form', // your agreement form
];
return $gates;
} );
add_action( 'wpal/torii/form_builder/submission/complete', function ( int $submission_id, int $form_id, array $data ): void {
if ( 42 !== $form_id ) { // your agreement form's ID
return;
}
$user_id = get_current_user_id();
if ( $user_id ) {
update_user_meta( $user_id, '_my_agreement_signed', time() );
}
}, 10, 3 );
Drop that in a must-use plugin, and the member who skips the agreement stays in the sandbox no matter what.
A roadmap note: a Form Builder action type that marks an onboarding gate complete on submission is planned; when it ships, the snippet goes away for most sites.
Tag-driven completion, and why to skip it
The Form Builder can apply a CRM tag on submission, and a custom gate's completion check could query tags instead of usermeta. It works, but it puts the release of a locked-out member in the hands of CRM sync latency and API availability. The member who just signed your agreement then waits on a webhook round trip before the site opens. Keep completion local: the form hook writes usermeta, the gate reads usermeta, and the sandbox lifts on the next request.
Which build is yours?
If you are unsure, start with the minimum build and the sandbox off. Watch where members stall (the module tracks gate completion for this), then decide whether the stalling step deserves to be a gate or a better page. Most funnels end up at the recommended build: one enforced gate, two good pages, no code.