[ 'gpt-4-turbo' ], 16 => [ 'gpt-4-turbo', 'gpt-4.1' ], 17 => [ 'gpt-4-turbo', 'gpt-4.1', 'gpt-4o' ], 18 => [ 'gpt-4-turbo', 'gpt-4.1', 'gpt-4o' ], ][$lvl] ?? [ 'gpt-4-turbo' ]; } } /* ------------------------------------------------------------------ * Page renderer * - Renders both tabs, performs form handling, normalizes token * status fields from the API, and protects against invalid states. * ----------------------------------------------------------------*/ if ( ! function_exists( 'aish_render_settings_page' ) ) { function aish_render_settings_page() { $opts = get_option( AISH_OPT_KEY, [] ); $token = $opts['site_token'] ?? ''; $model = $opts['model_choice'] ?? 'gpt-4-turbo'; $tab = ( isset($_GET['tab']) && $_GET['tab']==='seo-settings' ) ? 'seo-settings' : 'site-key'; /* -------------------------------------------------------------- * POST handlers (CSRF + capability checks) * ------------------------------------------------------------*/ if ( isset($_POST['aish_action']) && check_admin_referer($_POST['aish_action']) ){ if ( ! current_user_can('manage_options') ) { wp_die('Insufficient permissions'); } /* -- Save: Site Key -------------------------------------- */ if ( $_POST['aish_action'] === 'aish_save_site_key' ){ $newKey = sanitize_text_field( wp_unslash( $_POST['site_token'] ?? '' ) ); // Force refresh first; fall back to legacy signature if needed try { $test = aish_check_token_status( $newKey, true ); } catch (Throwable $e) { $test = aish_check_token_status( $newKey ); // legacy signature fallback } if ( ! empty( $test['error'] ) ){ echo '

Site Key Error: ' . esc_html( $test['error'] ) . '

'; unset( $opts['site_token'] ); }else{ $opts['site_token'] = $newKey; echo '

Site Key saved.

'; } update_option( AISH_OPT_KEY, $opts ); $token = $opts['site_token'] ?? ''; $tab = 'site-key'; /* -- Save: SEO settings (model, prompt, auto-slug) ------- */ }elseif ( $_POST['aish_action'] === 'aish_save_seo_settings' ){ $mc = sanitize_text_field( wp_unslash( $_POST['model_choice'] ?? 'gpt-4-turbo' ) ); $opts['model_choice'] = $mc; $opts['custom_prompt'] = sanitize_textarea_field( wp_unslash( $_POST['custom_prompt'] ?? '' ) ); /* Auto-slug toggle (ON writes AI slug & keeps _wp_old_slug) */ $opts['auto_slug'] = ( isset($_POST['auto_slug']) && $_POST['auto_slug'] === 'yes' ) ? 'yes' : 'no'; update_option( AISH_OPT_KEY, $opts ); $model = $mc; $tab = 'seo-settings'; echo '

Settings saved.

'; } } /* -------------------------------------------------------------- * Token / Membership normalization * - Reads multiple possible keys from API responses to remain * compatible across versions. Falls back progressively. * ------------------------------------------------------------*/ $usage = $limit = $remain = $site_usage = null; $allowed = [ 'gpt-4-turbo' ]; // default fallback $membership = 'free'; /* 1) Always attempt a fresh token-info on this page */ if ( $token ) { try { $st = aish_check_token_status( $token, true ); // force refresh } catch (Throwable $e) { $st = aish_check_token_status( $token ); // legacy signature fallback } if ( empty( $st['error'] ) ) { /* ---- Read raw fields (tolerate different API shapes) ---- */ $site_usage = (int) ( $st['site_usage'] ?? 0 ); $limit = (int) ( $st['plan_limit_total'] ?? $st['plan_limit'] ?? $st['token_limit'] ?? 0 ); /* Global usage (all sites) – probe several keys */ $usage_total = null; foreach ( ['usage_total','all_usage','total_usage','token_usage','usage'] as $k ){ if ( isset($st[$k]) ) { $usage_total = (int)$st[$k]; break; } } /* Global remaining – probe several keys */ $remain_total = null; foreach ( ['remaining_total','remaining_all','global_remaining'] as $k ){ if ( isset($st[$k]) ) { $remain_total = (int)$st[$k]; break; } } /* Sometimes only a generic 'remaining' exists */ if ( $remain_total === null && isset($st['remaining']) ) { $remain_total = (int)$st['remaining']; } /* ---- Derived values when parts are missing ---- */ if ( $usage_total === null && $limit > 0 && $remain_total !== null ) { $usage_total = max(0, $limit - $remain_total); } if ( $remain_total === null && $limit > 0 && $usage_total !== null ) { $remain_total = max(0, $limit - $usage_total); } if ( $usage_total === null ) { $usage_total = max( 0, (int)$site_usage ); } /* Final normalized numbers used by the UI */ $usage = (int) $usage_total; $remain = (int) aish_status_remaining( $st ); // allowed models from API if ( ! empty( $st['allowed_models'] ) && is_array( $st['allowed_models'] ) ) { $allowed = array_values( array_unique( array_map( 'strval', $st['allowed_models'] ) ) ); } } } /* 2) PMPro override — if API says "free", map WP level to plan */ if ( function_exists( 'pmpro_getMembershipLevelForUser' ) ) { $lvlObj = pmpro_getMembershipLevelForUser(); $lvlId = $lvlObj ? (int) $lvlObj->id : 15; // 15 = Free if ( $membership === 'free' ) { if ( $lvlId === 18 ) $membership = 'expert'; elseif ( $lvlId === 17 ) $membership = 'creator'; elseif ( $lvlId === 16 ) $membership = 'starter'; } } /* 3) Allowed model list derived from the final membership */ switch ( $membership ) { case 'starter': $allowed = [ 'gpt-4-turbo', 'gpt-4.1' ]; break; case 'creator': case 'expert': $allowed = [ 'gpt-4-turbo', 'gpt-4.1', 'gpt-4o' ]; break; default: /* free → turbo only */ $membership = 'free'; $allowed = [ 'gpt-4-turbo' ]; } /* 4) Extra heuristics * - User meta tokens & plan limit can bump or constrain access. * - Ensures UI never offers a model that cannot be used. */ $user_id = get_current_user_id(); $plan_tokens = (int) get_user_meta( $user_id, 'ai-snippet-seo-helper_membership_tokens', // helper-specific user meta true ); if ( $plan_tokens > 25 && $membership === 'free' ) { $membership = 'starter'; $allowed = [ 'gpt-4-turbo', 'gpt-4.1' ]; } /* Limit-based adjustment — tiny limits imply Free */ if ( is_int($limit) && $limit <= 25 ) { $membership = 'free'; $allowed = [ 'gpt-4-turbo' ]; } else { // High limit but membership still “free” → promote to Starter if ( $membership === 'free' ) { $membership = 'starter'; $allowed = [ 'gpt-4-turbo', 'gpt-4.1' ]; } } /* 5) Safety: if the saved model is not in $allowed, fall back */ if ( ! in_array( $model, $allowed, true ) ) { $model = 'gpt-4-turbo'; $opts['model_choice'] = $model; update_option( AISH_OPT_KEY, $opts ); } /* 6) CTA (button label & URL) depends on membership tier */ if ( $membership === 'free' ) { $token_btn_label = 'GET PREMIUM NOW'; $token_btn_url = 'https://rankpilotai.com/ai-snippet-seo-helper-pricing/'; } else { $token_btn_label = 'BUY TOKENS'; $token_btn_url = 'https://rankpilotai.com/tokens-2/?plugin=ai-snippet-seo-helper'; } /* ======================= HTML OUTPUT ======================= */ ?>

RankPilotAI – Site Key

Enter your Site Key below to get started.

Generate a Site Key in your account at RankPilotAI.com

Your Active Site Key

Usage Overview

This Site Usage Plan Limit Remaining Progress

Update / Change Site Key

SEO Snippet Settings

These settings control how AI Snippet SEO Helper generates snippets inside the Rank Math SEO snippet editor. Rank Math SEO must be installed and active.

Models are provided by the external RankPilotAI service. Some models may be unavailable on your current plan with that service.

A base prompt already ensures SEO compliance.
Add tone or extra instructions here to be appended on top of ours.

Default OFF. When enabled the AI-generated slug overwrites the old one.
WordPress keeps the previous slug in _wp_old_slug and serves a 301 redirect.

← enter a Site Key first