prefix . 'cloudprime_chat_logs'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, session_id varchar(32) NOT NULL, user_message text NOT NULL, ai_response text NOT NULL, contact_info text DEFAULT NULL, whmcs_client_id int DEFAULT NULL, ai_provider varchar(20) DEFAULT 'openrouter', created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // Contacts table $table_name = $wpdb->prefix . 'cloudprime_contacts'; $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, session_id varchar(32) NOT NULL, name varchar(255) NOT NULL, phone varchar(50) NOT NULL, email varchar(255) DEFAULT NULL, whmcs_client_id int DEFAULT NULL, source varchar(50) DEFAULT 'chatbot', created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; dbDelta($sql); // Visitor tracking table $table_name = $wpdb->prefix . 'cloudprime_visitors'; $sql = "CREATE TABLE $table_name ( id BIGINT NOT NULL AUTO_INCREMENT, ip VARCHAR(45), user_agent TEXT, referrer TEXT, landing_page VARCHAR(512), geo_country CHAR(3), geo_city VARCHAR(100), session_id VARCHAR(64), first_seen DATETIME DEFAULT CURRENT_TIMESTAMP, last_seen DATETIME DEFAULT CURRENT_TIMESTAMP, page_views INT DEFAULT 1, PRIMARY KEY (id), KEY session_idx (session_id) ) $charset_collate;"; dbDelta($sql); cloudprime_debug_log('Enhanced tables created with WHMCS integration'); } // Admin menu add_action('admin_menu', function() { add_menu_page( 'CloudPrime Chatbot', 'CloudPrime Chatbot', 'manage_options', 'cloudprime-chatbot', 'cloudprime_chatbot_admin_page_content', 'dashicons-format-chat', 6 ); add_submenu_page( 'cloudprime-chatbot', 'Chat Logs', 'Chat Logs', 'manage_options', 'cloudprime-chat-logs', 'cloudprime_chatbot_logs_page' ); add_submenu_page( 'cloudprime-chatbot', 'Contacts', 'Contacts', 'manage_options', 'cloudprime-contacts', 'cloudprime_chatbot_contacts_page' ); add_submenu_page( 'cloudprime-chatbot', 'WHMCS Settings', 'WHMCS Settings', 'manage_options', 'cloudprime-whmcs', 'cloudprime_whmcs_settings_page' ); /* NEW: Visitor analytics page */ add_submenu_page( 'cloudprime-chatbot', 'Visitor Analytics', 'Visitor Analytics', 'manage_options', 'cloudprime-analytics', 'cloudprime_analytics_page' ); }); /* ---------- NEW: Visitor analytics page handler ---------- */ function cloudprime_analytics_page() { global $wpdb; $rows = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}cloudprime_visitors ORDER BY last_seen DESC LIMIT 1000"); ?>

Visitor Analytics

Export CSV

IPCountryCityLandingViewsLast Seen
ip); ?> geo_country); ?> geo_city); ?> landing_page, 5)); ?> page_views; ?> last_seen); ?>
get_results("SELECT * FROM {$wpdb->prefix}cloudprime_visitors", ARRAY_A); header('Content-Type: text/csv'); header('Content-Disposition: attachment;filename=visitors.csv'); $out = fopen('php://output', 'w'); fputcsv($out, array_keys($rows[0] ?? [])); foreach ($rows as $r) fputcsv($out, $r); fclose($out); exit; }); function cloudprime_chatbot_admin_page_content() { // Handle form submission if (isset($_POST['submit'])) { $settings = [ 'ai_provider' => sanitize_text_field($_POST['ai_provider'] ?? 'openrouter'), 'openrouter_api_key' => sanitize_text_field($_POST['openrouter_api_key'] ?? ''), 'gemini_api_key' => sanitize_text_field($_POST['gemini_api_key'] ?? ''), 'whatsapp_number' => sanitize_text_field($_POST['whatsapp_number'] ?? ''), 'ai_name' => sanitize_text_field($_POST['ai_name'] ?? 'CloudPrime Assistant'), 'ai_avatar_url' => esc_url_raw($_POST['ai_avatar_url'] ?? ''), 'predefined_questions_setting' => sanitize_textarea_field($_POST['predefined_questions_setting'] ?? ''), 'enable_conditional_whatsapp' => isset($_POST['enable_conditional_whatsapp']) ? 1 : 0, 'notification_email' => sanitize_email($_POST['notification_email'] ?? get_option('admin_email')), 'enable_whmcs_integration' => isset($_POST['enable_whmcs_integration']) ? 1 : 0, 'enable_voice_commands' => isset($_POST['enable_voice_commands']) ? 1 : 0 ]; update_option('cloudprime_chatbot_settings', $settings); echo '

Settings saved successfully!

'; } $opts = get_option('cloudprime_chatbot_settings', []); ?>

CloudPrime Chatbot Settings

Debug Information

Plugin Status: Not configured (API key missing)' : 'Configured (' . $provider . ')'; ?>

WHMCS Integration: Enabled' : 'Disabled'; ?>

Voice Commands: Enabled' : 'Disabled'; ?>

Current Theme:

AI Provider

Choose your preferred AI provider.

OpenRouter API Key

Get a key from openrouter.ai

Google Gemini API Key

Get a key from Google AI Studio

WhatsApp Number

Format: 27101108466 (no spaces or special chars)

AI Name

The name displayed for the AI chatbot.

AI Avatar URL

URL to the AI's avatar image.

Predefined Questions

Enter each question on a new line.

Enable Conditional WhatsApp Button >

If enabled, the WhatsApp button will only appear when the AI cannot answer a question or when the client asks to speak to a human.

Enable Voice Commands >

Enable voice recognition for hands-free interaction.

Enable WHMCS Integration >

Enable integration with WHMCS for client support features.

Notification Email

Email address to receive new contact notifications.

get_results("SELECT * FROM {$wpdb->prefix}cloudprime_chat_logs ORDER BY created_at DESC LIMIT 100"); ?>

Chat Logs

Date Session ID User Message AI Response AI Provider WHMCS Client Contact Info
created_at); ?> session_id, 0, 8)); ?>... user_message, 10)); ?> ai_response, 15)); ?> ai_provider ?? 'openrouter'); ?> whmcs_client_id ? esc_html($log->whmcs_client_id) : '-'; ?> contact_info); ?>
get_results("SELECT * FROM {$wpdb->prefix}cloudprime_contacts ORDER BY created_at DESC"); ?>

Contacts

Date Name Phone Email WHMCS Client ID Source
created_at); ?> name); ?> phone); ?> email); ?> whmcs_client_id ? esc_html($contact->whmcs_client_id) : '-'; ?> source); ?>
esc_url_raw($_POST['whmcs_url'] ?? ''), 'whmcs_api_identifier' => sanitize_text_field($_POST['whmcs_api_identifier'] ?? ''), 'whmcs_api_secret' => sanitize_text_field($_POST['whmcs_api_secret'] ?? ''), 'whmcs_db_host' => sanitize_text_field($_POST['whmcs_db_host'] ?? ''), 'whmcs_db_name' => sanitize_text_field($_POST['whmcs_db_name'] ?? ''), 'whmcs_db_user' => sanitize_text_field($_POST['whmcs_db_user'] ?? ''), 'whmcs_db_pass' => sanitize_text_field($_POST['whmcs_db_pass'] ?? ''), 'whmcs_integration_method' => sanitize_text_field($_POST['whmcs_integration_method'] ?? 'api') ]; update_option('cloudprime_whmcs_settings', $whmcs_settings); echo '

WHMCS settings saved successfully!

'; } $whmcs_opts = get_option('cloudprime_whmcs_settings', []); ?>

WHMCS Integration Settings

Integration Method

Choose how to connect to WHMCS.

WHMCS URL

Your WHMCS installation URL (e.g., https://billing.cloudprime.co.za)

API Identifier

WHMCS API Identifier from Setup > General Settings > Security

API Secret

WHMCS API Secret

Database Host

WHMCS database host (usually localhost)

Database Name

WHMCS database name

Database Username

WHMCS database username

Database Password

WHMCS database password

'GetClientsDetails', 'email' => $email, 'identifier' => $identifier, 'secret' => $secret, 'responsetype' => 'json' ]; $response = wp_remote_post($url . '/includes/api.php', ['body' => $postdata, 'timeout' => 10]); if (is_wp_error($response)) return null; $result = json_decode(wp_remote_retrieve_body($response), true); return isset($result['result']) && $result['result'] === 'success' ? $result : null; } function cloudprime_whmcs_db_get_client($email) { $whmcs_opts = get_option('cloudprime_whmcs_settings', []); $host = $whmcs_opts['whmcs_db_host'] ?? ''; $dbname = $whmcs_opts['whmcs_db_name'] ?? ''; $username = $whmcs_opts['whmcs_db_user'] ?? ''; $password = $whmcs_opts['whmcs_db_pass'] ?? ''; if (empty($host) || empty($dbname) || empty($username)) return null; try { $whmcs_db = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); $whmcs_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $whmcs_db->prepare("SELECT * FROM tblclients WHERE email = ?"); $stmt->execute([$email]); $client = $stmt->fetch(PDO::FETCH_ASSOC); if (!$client) return null; $stmt = $whmcs_db->prepare("SELECT * FROM tblinvoices WHERE userid = ? ORDER BY id DESC LIMIT 5"); $stmt->execute([$client['id']]); $invoices = $stmt->fetchAll(PDO::FETCH_ASSOC); $stmt = $whmcs_db->prepare("SELECT * FROM tbltickets WHERE userid = ? ORDER BY id DESC LIMIT 5"); $stmt->execute([$client['id']]); $tickets = $stmt->fetchAll(PDO::FETCH_ASSOC); $stmt = $whmcs_db->prepare("SELECT COUNT(*) as unpaid_count, SUM(total) as unpaid_total FROM tblinvoices WHERE userid = ? AND status = 'Unpaid'"); $stmt->execute([$client['id']]); $unpaid = $stmt->fetch(PDO::FETCH_ASSOC); return ['client'=>$client,'invoices'=>$invoices,'tickets'=>$tickets,'unpaid_invoices'=>$unpaid]; } catch (PDOException $e) { cloudprime_debug_log('WHMCS DB Error: ' . $e->getMessage()); return null; } } /* ================================================================================= * NEW SHARED WHMCS CRUD HELPERS * ================================================================================= */ function cloudprime_api_call($action, $params = []) { $opts = get_option('cloudprime_whmcs_settings', []); $url = rtrim($opts['whmcs_url'] ?? '', '/') . '/includes/api.php'; $id = $opts['whmcs_api_identifier'] ?? ''; $sec = $opts['whmcs_api_secret'] ?? ''; if (!$id || !$sec) return ['error' => 'WHMCS API not configured']; $body = array_merge($params, ['action' => $action, 'username' => $id, 'password' => $sec, 'responsetype' => 'json']); $resp = wp_remote_post($url, ['body' => $body, 'timeout' => 15]); if (is_wp_error($resp)) return ['error' => $resp->get_error_message()]; return json_decode($resp['body'], true) ?: ['error' => 'Invalid JSON']; } /* ---------- NEW: Visitor tracking helpers ---------- */ add_action('wp_footer', 'cloudprime_track_visitor'); function cloudprime_track_visitor() { if (is_admin()) return; global $wpdb; $ip = cloudprime_real_ip(); $ua = sanitize_text_field($_SERVER['HTTP_USER_AGENT'] ?? ''); $ref = sanitize_text_field($_SERVER['HTTP_REFERER'] ?? ''); $page = home_url(add_query_arg(null, null)); $sid = cloudprime_session_id(); $country = sanitize_text_field($_SERVER['HTTP_CF_IPCOUNTRY'] ?? ''); $city = ''; $row = $wpdb->get_row($wpdb->prepare( "SELECT id, page_views FROM {$wpdb->prefix}cloudprime_visitors WHERE session_id = %s", $sid )); if ($row) { $wpdb->update( "{$wpdb->prefix}cloudprime_visitors", [ 'last_seen' => current_time('mysql'), 'page_views' => $row->page_views + 1 ], ['id' => $row->id] ); } else { $wpdb->insert( "{$wpdb->prefix}cloudprime_visitors", [ 'ip' => $ip, 'user_agent' => $ua, 'referrer' => $ref, 'landing_page' => $page, 'geo_country' => $country, 'geo_city' => $city, 'session_id' => $sid ] ); } } function cloudprime_session_id() { if (isset($_COOKIE['cp_session'])) return $_COOKIE['cp_session']; $sid = bin2hex(random_bytes(16)); setcookie('cp_session', $sid, time() + 30 * DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN); return $sid; } function cloudprime_real_ip() { return $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; } /* ================================================================================= * NEW WHMCS CRUD ENDPOINTS (add all requested write-actions) * ================================================================================= */ $whmcs_actions = [ 'cloudprime_create_client' => function ($p) { return cloudprime_api_call('AddClient', $p); }, 'cloudprime_update_client' => function ($p) { return cloudprime_api_call('UpdateClient', array_merge(['clientid'=>intval($p['client_id'])], $p)); }, 'cloudprime_create_invoice' => function ($p) { return cloudprime_api_call('CreateInvoice', ['clientid'=>intval($p['client_id']),'lineitems'=>$p['items']]); }, 'cloudprime_pay_invoice' => function ($p) { return cloudprime_api_call('AddInvoicePayment', ['invoiceid'=>intval($p['invoice_id']),'amount'=>floatval($p['amount']),'paymentmethod'=>'credit']); }, 'cloudprime_open_ticket' => function ($p) { return cloudprime_api_call('OpenTicket', ['clientid'=>intval($p['client_id']),'deptid'=>intval($p['dept']),'subject'=>sanitize_text_field($p['subject']),'message'=>sanitize_textarea_field($p['message'])]); }, 'cloudprime_close_ticket' => function ($p) { return cloudprime_api_call('UpdateTicket', ['ticketid'=>intval($p['ticket_id']),'status'=>'Closed']); }, 'cloudprime_order_service' => function ($p) { return cloudprime_api_call('AddOrder', ['clientid'=>intval($p['client_id']),'pid'=>intval($p['pid']),'domain'=>sanitize_text_field($p['domain'])]); }, 'cloudprime_suspend_service' => function ($p) { return cloudprime_api_call('ModuleSuspend', ['serviceid'=>intval($p['service_id']),'suspendreason'=>sanitize_text_field($p['reason'])]); }, 'cloudprime_domain_action' => function ($p) { return cloudprime_api_call('Domain'.ucfirst(sanitize_text_field($p['action'])), ['domain'=>sanitize_text_field($p['domain']),'regperiod'=>intval($p['years']??1)]); } ]; foreach ($whmcs_actions as $hook => $fn) { add_action("wp_ajax_$hook", function () use ($fn) { check_ajax_referer('cloudprime_chat_nonce'); wp_send_json($fn($_POST)); }); } /* ================================================================================= * ORIGINAL AI FUNCTIONS (unchanged) * ================================================================================= */ function cloudprime_get_ai_response($prompt, $client_data = null, $provider = 'openrouter') { $opt = get_option('cloudprime_chatbot_settings'); return $provider === 'gemini' ? cloudprime_get_gemini_response($prompt, $client_data, $opt) : cloudprime_get_openrouter_response($prompt, $client_data, $opt); } function cloudprime_get_gemini_response($prompt, $client_data, $opt) { $key = $opt['gemini_api_key'] ?? ''; if (!$key) return ['error' => 'Gemini API key not configured']; $sys = cloudprime_build_system_prompt($client_data); $body = json_encode([ 'contents' => [['parts' => [['text' => $sys . "\n\nUser: " . $prompt]]]], 'generationConfig' => ['temperature' => 0.7, 'maxOutputTokens' => 400] ]); $resp = wp_remote_post("https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=$key", [ 'headers' => ['Content-Type' => 'application/json'], 'body' => $body, 'timeout' => 20 ]); if (is_wp_error($resp)) return ['error' => $resp->get_error_message()]; $res = json_decode(wp_remote_retrieve_body($resp), true); return isset($res['candidates'][0]['content']['parts'][0]['text']) ? ['reply' => $res['candidates'][0]['content']['parts'][0]['text']] : ['error' => 'Invalid Gemini response']; } function cloudprime_get_openrouter_response($prompt, $client_data, $opt) { $key = $opt['openrouter_api_key'] ?? ''; if (!$key) return ['error' => 'OpenRouter API key not configured']; $sys = cloudprime_build_system_prompt($client_data); $body = json_encode([ "model" => "openrouter/auto", "max_tokens" => 400, "temperature" => 0.7, "messages" => [["role" => "system", "content" => $sys], ["role" => "user", "content" => $prompt]] ]); $resp = wp_remote_post("https://openrouter.ai/api/v1/chat/completions", [ "headers" => ["Authorization" => "Bearer $key", "Content-Type" => "application/json"], "body" => $body, "timeout" => 20 ]); if (is_wp_error($resp)) return ['error' => $resp->get_error_message()]; $res = json_decode(wp_remote_retrieve_body($resp), true); return isset($res['choices'][0]['message']['content']) ? ['reply' => $res['choices'][0]['message']['content']] : ['error' => 'Invalid OpenRouter response']; } function cloudprime_build_system_prompt($client_data = null) { /* identical to original – omitted for space */ return "...original prompt..."; } /* ================================================================================= * ORIGINAL AJAX HANDLERS (unchanged) * ================================================================================= */ add_action('wp_ajax_cloudprime_chat', 'cloudprime_handle_chat_ajax'); add_action('wp_ajax_nopriv_cloudprime_chat', 'cloudprime_handle_chat_ajax'); function cloudprime_handle_chat_ajax() { check_ajax_referer('cloudprime_chat_nonce', 'nonce'); $message = sanitize_text_field($_POST['message']); $session_id = sanitize_text_field($_POST['session_id']); $email = sanitize_email($_POST['email'] ?? ''); $opts = get_option('cloudprime_chatbot_settings'); $provider = $opts['ai_provider'] ?? 'openrouter'; $client_data = null; $whmcs_client_id = null; if (!empty($email) && !empty($opts['enable_whmcs_integration'])) { $client_data = cloudprime_get_whmcs_client_by_email($email); if ($client_data && isset($client_data['client'])) $whmcs_client_id = $client_data['client']['id']; } $ai_response = cloudprime_get_ai_response($message, $client_data, $provider); if (isset($ai_response['error'])) { wp_send_json_error($ai_response['error']); return; } global $wpdb; $wpdb->insert($wpdb->prefix . 'cloudprime_chat_logs', [ 'session_id' => $session_id, 'user_message' => $message, 'ai_response' => $ai_response['reply'], 'contact_info' => $email, 'whmcs_client_id' => $whmcs_client_id, 'ai_provider' => $provider, 'created_at' => current_time('mysql') ]); $show_whatsapp = false; if (!empty($opts['enable_conditional_whatsapp'])) { $triggers = ['speak to human','human agent','contact support','call you','cannot help','don\'t know']; foreach ($triggers as $t) if (stripos($ai_response['reply'], $t) !== false || stripos($message, $t) !== false) {$show_whatsapp = true; break;} } wp_send_json_success([ 'message' => $ai_response['reply'], 'show_whatsapp' => $show_whatsapp, 'client_info' => $client_data ? [ 'name' => $client_data['client']['firstname'] . ' ' . $client_data['client']['lastname'], 'client_id' => $client_data['client']['id'], 'status' => $client_data['client']['status'] ] : null ]); } /* ================================================================================= * ORIGINAL CONTACT AJAX HANDLER (unchanged) * ================================================================================= */ add_action('wp_ajax_cloudprime_save_contact', 'cloudprime_save_contact_ajax'); add_action('wp_ajax_nopriv_cloudprime_save_contact', 'cloudprime_save_contact_ajax'); function cloudprime_save_contact_ajax() { check_ajax_referer('cloudprime_chat_nonce', 'nonce'); $name = sanitize_text_field($_POST['name']); $phone = sanitize_text_field($_POST['phone']); $email = sanitize_email($_POST['email']); $session_id = sanitize_text_field($_POST['session_id']); $whmcs_client_id = null; $opts = get_option('cloudprime_chatbot_settings'); if (!empty($opts['enable_whmcs_integration']) && !empty($email)) { $client_data = cloudprime_get_whmcs_client_by_email($email); if ($client_data && isset($client_data['client'])) $whmcs_client_id = $client_data['client']['id']; } global $wpdb; $result = $wpdb->insert($wpdb->prefix . 'cloudprime_contacts', [ 'session_id' => $session_id, 'name' => $name, 'phone' => $phone, 'email' => $email, 'whmcs_client_id' => $whmcs_client_id, 'source' => 'chatbot', 'created_at' => current_time('mysql') ]); if ($result) { $notification_email = $opts['notification_email'] ?? get_option('admin_email'); $subject = 'New Contact from CloudPrime Chatbot'; $message = "New contact submitted via chatbot:\n\nName: $name\nPhone: $phone\nEmail: $email\n" . ($whmcs_client_id ? "WHMCS Client ID: $whmcs_client_id\n" : '') . "Session ID: $session_id\nDate: " . current_time('mysql') . "\n"; wp_mail($notification_email, $subject, $message); wp_send_json_success([ 'message' => 'Thank you! Your contact information has been saved.', 'predefined_questions' => array_filter(explode("\n", $opts['predefined_questions_setting'] ?? '')) ]); } else { wp_send_json_error('Failed to save contact information'); } } /* ================================================================================= * ORIGINAL FRONT-END CHATBOT (unchanged except voice fix) * ================================================================================= */ add_action('wp_footer', 'cloudprime_chatbot_frontend'); function cloudprime_chatbot_frontend() { $opts = get_option('cloudprime_chatbot_settings'); $provider = $opts['ai_provider'] ?? 'openrouter'; $key_field = $provider === 'gemini' ? 'gemini_api_key' : 'openrouter_api_key'; if (empty($opts[$key_field])) return; $ai_name = $opts['ai_name'] ?? 'CloudPrime Assistant'; $ai_avatar = $opts['ai_avatar_url'] ?? ''; $whatsapp_number = $opts['whatsapp_number'] ?? ''; $predefined_questions = array_filter(explode("\n", $opts['predefined_questions_setting'] ?? '')); $enable_voice = !empty($opts['enable_voice_commands']); ?>
💬