uspw_before_spin_validation
The uspw_before_spin_validation filter runs on the server at the very start of a spin request, right after the built-in field checks and before any prize is drawn or saved. Return false to block the spin. It is the ideal place to add custom eligibility rules such as rate limiting, authentication checks, or business-hours restrictions.
Important — this hook only fires when the Ultimate Spin Wheel Pro plugin is active (Pro). In the core (free) plugin the call is wrapped in if ( apply_filters( 'ultimate_spin_wheel_pro_init', false ) ), so your callback will never run unless Pro is installed and active. Build against it only in Pro environments.
Signature
Type: Filter · Since: 1.0.0 · Location: includes/core/class-spin-wheel.php
$can_spin = apply_filters( 'uspw_before_spin_validation', $can_spin, $campaign_id, $user_data );
Parameters
bool $can_spin— Whether the user may spin. Defaults totrue. Returnfalseto block.int $campaign_id— The ID of the spin wheel campaign being played.array $user_data— The submitted lead data, sanitized by the plugin. It contains exactly three keys:email,phone, andname. (Thephonefield is only collected when the Pro phone input is enabled; otherwise it is an empty string.) Any other posted values must be read from$_POSTdirectly.
Basic Usage
Because it is a filter, hook it with add_filter() and always return a boolean. Returning false stops the spin, after which the plugin responds with a generic “You are not eligible to spin at this time.” message.
add_filter( 'uspw_before_spin_validation', 'my_custom_validation', 10, 3 );
function my_custom_validation( $can_spin, $campaign_id, $user_data ) {
// Your custom logic here.
return $can_spin; // true = allow, false = block
}
Showing a custom block message: the return value only carries a boolean, so it cannot pass a message. If you need a specific reason shown to the visitor, call wp_send_json_error() inside your callback — it halts the AJAX request immediately with your text. Otherwise just return false and let the plugin show its default message.
Example 1: Block Specific Email Domains
Prevent competitor or unwanted domains from spinning. Note that the free plugin already includes a built-in disposable-email blocker (toggled in global settings), so use this for your own custom domain list.
add_filter( 'uspw_before_spin_validation', 'block_custom_domains', 10, 3 );
function block_custom_domains( $can_spin, $campaign_id, $user_data ) {
$blocked = [ 'competitor.com', 'example-spam.com' ];
if ( ! empty( $user_data['email'] ) ) {
$domain = substr( strrchr( $user_data['email'], '@' ), 1 );
if ( in_array( strtolower( $domain ), $blocked, true ) ) {
wp_send_json_error( [ 'message' => 'Please use a different email address.' ] );
}
}
return $can_spin;
}
Example 2: Rate-Limit by IP Address
Restrict spins per IP within a timeframe. Leads are stored in the custom table wp_wdengage_entries (with campaign_id, ip_address, and created_at columns). The free plugin also offers built-in IP blocking and manual IP/device blocking if you only need to ban known addresses.
add_filter( 'uspw_before_spin_validation', 'limit_spins_by_ip', 10, 3 );
function limit_spins_by_ip( $can_spin, $campaign_id, $user_data ) {
global $wpdb;
$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
$table = $wpdb->prefix . 'wdengage_entries';
$count = (int) $wpdb->get_var( $wpdb->prepare(
"SELECT COUNT(*) FROM {$table} WHERE campaign_id = %d AND ip_address = %s AND created_at > DATE_SUB( NOW(), INTERVAL 24 HOUR )",
$campaign_id, $ip
) );
if ( $count >= 3 ) {
return false; // Plugin shows the default "not eligible" message.
}
return $can_spin;
}
Example 3: Require Login for Certain Campaigns
Force visitors to be logged in before spinning specific campaigns.
add_filter( 'uspw_before_spin_validation', 'require_login_for_campaigns', 10, 3 );
function require_login_for_campaigns( $can_spin, $campaign_id, $user_data ) {
$members_only = [ 123, 456, 789 ];
if ( in_array( $campaign_id, $members_only, true ) && ! is_user_logged_in() ) {
wp_send_json_error( [ 'message' => 'Please log in to participate.' ] );
}
return $can_spin;
}
Example 4: Validate a Submitted Field
Enforce a minimum phone length on campaigns that collect a phone number (the Pro phone field). Fields outside the three keys in $user_data — such as a custom company input — must be read from $_POST and sanitized yourself.
add_filter( 'uspw_before_spin_validation', 'validate_submitted_fields', 10, 3 );
function validate_submitted_fields( $can_spin, $campaign_id, $user_data ) {
if ( ! empty( $user_data['phone'] ) ) {
$digits = preg_replace( '/[^0-9]/', '', $user_data['phone'] );
if ( strlen( $digits ) < 10 ) {
wp_send_json_error( [ 'message' => 'Please enter a valid 10-digit phone number.' ] );
}
}
return $can_spin;
}
Example 5: Time-Based Restrictions
Allow spins only during set hours or days. For simple start/end date ranges, Pro also has a built-in campaign scheduling option — use this hook when you need finer, code-driven control.
add_filter( 'uspw_before_spin_validation', 'business_hours_only', 10, 3 );
function business_hours_only( $can_spin, $campaign_id, $user_data ) {
if ( 999 === (int) $campaign_id ) {
$now = new DateTime( 'now', new DateTimeZone( 'America/New_York' ) );
$hour = (int) $now->format( 'H' );
if ( $hour < 9 || $hour >= 17 ) {
wp_send_json_error( [ 'message' => 'Available between 9 AM and 5 PM EST.' ] );
}
}
return $can_spin;
}
Notes & Best Practices
- This is a filter — always return a boolean. Do not rely on a by-reference “block” argument; none exists.
- The hook only runs when the Ultimate Spin Wheel Pro (Pro) plugin is active. In the free plugin it is skipped entirely.
- It fires early — after the plugin’s built-in email/phone/name checks but before prize selection and any database write — so it is well suited to rate limiting, authentication, and business-logic gates.
- Return
falsefor the plugin’s default block message, or callwp_send_json_error()yourself to show a custom reason. - Before reinventing a check, remember the free plugin already ships honeypot protection, IP blocking, manual IP/device blocking, and disposable-email blocking; identity checks and cooldowns are available in Pro.
Related Documentation
- Developer Hooks & Filters: The full list of
uspw_*hooks and their firing order. - Win Probabilities: How the server draws a winner after validation passes.
Conclusion
The uspw_before_spin_validation filter is your entry point for custom, server-side spin eligibility rules in Pro. Return true to allow or false to block, and call wp_send_json_error() when you need a tailored message. If you need help, visit the wowDevs support center.