Changeset 3408429
- Timestamp:
- 12/02/2025 08:00:30 PM (6 weeks ago)
- Location:
- opti-behavior
- Files:
-
- 96 added
- 2 deleted
- 22 edited
-
assets/xicon-128x128.png (deleted)
-
assets/xicon-256x256.png (deleted)
-
tags/1.0.7 (added)
-
tags/1.0.7/Opti-Behavior.php (added)
-
tags/1.0.7/THIRD-PARTY-LICENSES.md (added)
-
tags/1.0.7/admin (added)
-
tags/1.0.7/admin/class-opti-behavior-heatmap-admin-settings.php (added)
-
tags/1.0.7/admin/class-opti-behavior-heatmap-ajax-handler.php (added)
-
tags/1.0.7/admin/class-opti-behavior-heatmap-dashboard.php (added)
-
tags/1.0.7/admin/class-opti-behavior-heatmap-list.php (added)
-
tags/1.0.7/admin/class-opti-behavior-heatmap-post-metabox.php (added)
-
tags/1.0.7/admin/recordings-upgrade-page.php (added)
-
tags/1.0.7/assets (added)
-
tags/1.0.7/assets/css (added)
-
tags/1.0.7/assets/css/admin-menu.css (added)
-
tags/1.0.7/assets/css/admin-notices.css (added)
-
tags/1.0.7/assets/css/admin-utilities.css (added)
-
tags/1.0.7/assets/css/ai-insights-page.css (added)
-
tags/1.0.7/assets/css/countries-widget-scroll.css (added)
-
tags/1.0.7/assets/css/dashboard.css (added)
-
tags/1.0.7/assets/css/dashboard_styles.css (added)
-
tags/1.0.7/assets/css/heatmaps.css (added)
-
tags/1.0.7/assets/css/leaflet.min.css (added)
-
tags/1.0.7/assets/css/metabox.css (added)
-
tags/1.0.7/assets/css/recordings-upgrade.css (added)
-
tags/1.0.7/assets/css/sessions.css (added)
-
tags/1.0.7/assets/css/settings-modal.css (added)
-
tags/1.0.7/assets/css/settings.css (added)
-
tags/1.0.7/assets/css/style.css (added)
-
tags/1.0.7/assets/images (added)
-
tags/1.0.7/assets/images/OB.ico (added)
-
tags/1.0.7/assets/images/leaflet (added)
-
tags/1.0.7/assets/images/leaflet/layers-2x.png (added)
-
tags/1.0.7/assets/images/leaflet/layers.png (added)
-
tags/1.0.7/assets/images/leaflet/marker-icon-2x.png (added)
-
tags/1.0.7/assets/images/leaflet/marker-icon.png (added)
-
tags/1.0.7/assets/images/leaflet/marker-shadow.png (added)
-
tags/1.0.7/assets/js (added)
-
tags/1.0.7/assets/js/admin-utilities.js (added)
-
tags/1.0.7/assets/js/chart.umd.min.js (added)
-
tags/1.0.7/assets/js/dashboard-cleaned.js (added)
-
tags/1.0.7/assets/js/dashboard-converted.js (added)
-
tags/1.0.7/assets/js/dashboard-final.js (added)
-
tags/1.0.7/assets/js/dashboard.js (added)
-
tags/1.0.7/assets/js/frontend-mobile-simulator.js (added)
-
tags/1.0.7/assets/js/frontend-page-title.js (added)
-
tags/1.0.7/assets/js/heatmap.min.js (added)
-
tags/1.0.7/assets/js/heatmap.min.js.LICENSE.txt (added)
-
tags/1.0.7/assets/js/heatmaps.js (added)
-
tags/1.0.7/assets/js/leaflet-config.js (added)
-
tags/1.0.7/assets/js/leaflet.min.js (added)
-
tags/1.0.7/assets/js/lucide.min.js (added)
-
tags/1.0.7/assets/js/metabox-analytics.js (added)
-
tags/1.0.7/assets/js/mobile-simulator.js (added)
-
tags/1.0.7/assets/js/notice-cleanup.js (added)
-
tags/1.0.7/assets/js/opti-behavior-debug.js (added)
-
tags/1.0.7/assets/js/opti-behavior-heatmap-simple-fixed.js (added)
-
tags/1.0.7/assets/js/opti-behavior-heatmap-simple.js (added)
-
tags/1.0.7/assets/js/opti-behavior-heatmap.min.js (added)
-
tags/1.0.7/assets/js/settings.js (added)
-
tags/1.0.7/assets/js/support-form.js (added)
-
tags/1.0.7/includes (added)
-
tags/1.0.7/includes/class-autoloader.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-analytics.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-bot-tracker.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-core.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-data-protection.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-database.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-debug-manager.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-file-storage.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-options.php (added)
-
tags/1.0.7/includes/class-opti-behavior-heatmap-session.php (added)
-
tags/1.0.7/includes/class-opti-behavior-license-manager.php (added)
-
tags/1.0.7/includes/class-opti-behavior-performance-optimizer.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-ai-insights-views.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-ajax-handlers.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-assets.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-dashboard-views.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-data-helpers.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-exports.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-heatmaps-views.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-maintenance.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-sessions-views.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-settings-views.php (added)
-
tags/1.0.7/includes/trait-opti-behavior-settings-views.php.backup (added)
-
tags/1.0.7/languages (added)
-
tags/1.0.7/languages/opti-behavior-fr_FR.mo (added)
-
tags/1.0.7/languages/opti-behavior-fr_FR.po (added)
-
tags/1.0.7/languages/opti-behavior.pot (added)
-
tags/1.0.7/public (added)
-
tags/1.0.7/public/class-opti-behavior-heatmap-frontend.php (added)
-
tags/1.0.7/readme.txt (added)
-
tags/1.0.7/views (added)
-
tags/1.0.7/views/dashboard-views.php (added)
-
tags/1.0.7/views/heatmaps-views.php (added)
-
tags/1.0.7/views/sessions-views.php (added)
-
trunk/Opti-Behavior.php (modified) (8 diffs)
-
trunk/admin/class-opti-behavior-heatmap-ajax-handler.php (modified) (22 diffs)
-
trunk/admin/class-opti-behavior-heatmap-dashboard.php (modified) (3 diffs)
-
trunk/admin/class-opti-behavior-heatmap-post-metabox.php (modified) (11 diffs)
-
trunk/admin/recordings-upgrade-page.php (modified) (1 diff)
-
trunk/assets/css/dashboard_styles.css (modified) (1 diff)
-
trunk/assets/css/recordings-upgrade.css (modified) (3 diffs)
-
trunk/assets/js/dashboard.js (modified) (17 diffs)
-
trunk/assets/js/metabox-analytics.js (modified) (1 diff)
-
trunk/assets/js/opti-behavior-heatmap-simple-fixed.js (added)
-
trunk/assets/js/opti-behavior-heatmap-simple.js (modified) (7 diffs)
-
trunk/includes/class-opti-behavior-heatmap-analytics.php (modified) (1 diff)
-
trunk/includes/class-opti-behavior-heatmap-core.php (modified) (1 diff)
-
trunk/includes/class-opti-behavior-heatmap-database.php (modified) (1 diff)
-
trunk/includes/class-opti-behavior-heatmap-session.php (modified) (2 diffs)
-
trunk/includes/trait-opti-behavior-ai-insights-views.php (modified) (2 diffs)
-
trunk/includes/trait-opti-behavior-dashboard-views.php (modified) (1 diff)
-
trunk/includes/trait-opti-behavior-settings-views.php (modified) (1 diff)
-
trunk/includes/trait-opti-behavior-settings-views.php.backup (added)
-
trunk/languages/opti-behavior-fr_FR.mo (modified) (previous)
-
trunk/languages/opti-behavior-fr_FR.po (modified) (72 diffs)
-
trunk/readme.txt (modified) (3 diffs)
-
trunk/views/dashboard-views.php (modified) (24 diffs)
-
trunk/views/heatmaps-views.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
opti-behavior/trunk/Opti-Behavior.php
r3406294 r3408429 4 4 * Plugin URI: https://optiuser.com/ 5 5 * Description: Transform your WordPress site with powerful analytics! Track user behavior with beautiful heatmaps and real-time insights. Boost conversions and optimize user experience with data-driven decisions. 6 * Version: 1.0. 66 * Version: 1.0.7 7 7 * Author: OptiUser 8 8 * Author URI: https://optiuser.com/ … … 80 80 81 81 // Define plugin constants. 82 define( 'OPTI_BEHAVIOR_HEATMAP_VERSION', '1.0. 4.10' );82 define( 'OPTI_BEHAVIOR_HEATMAP_VERSION', '1.0.7' ); 83 83 define( 'OPTI_BEHAVIOR_HEATMAP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 84 84 define( 'OPTI_BEHAVIOR_HEATMAP_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 160 160 'override_load_textdomain', 161 161 function( $override, $domain, $mofile ) { 162 // Only apply to opti-behavior text domain163 if ( $domain !== 'opti-behavior' ) {162 // Only apply to opti-behavior and opti-behavior-pro text domains 163 if ( $domain !== 'opti-behavior' && $domain !== 'opti-behavior-pro' ) { 164 164 return $override; 165 165 } … … 178 178 'opti-behavior-analytics', 179 179 'opti-behavior-heatmaps', 180 'opti-behavior-heatmap-detail', 180 181 'opti-behavior-settings', 181 182 'opti-behavior-ai-insights', … … 187 188 } 188 189 189 if ( ! in_array( $current_page, $opti_behavior_pages, true ) ) { 190 // Check if we're doing an AJAX request for Opti-Behavior 191 $is_opti_behavior_ajax = false; 192 if ( wp_doing_ajax() ) { 193 // phpcs:disable WordPress.Security.NonceVerification.Missing -- POST parameter used for action identification only (read-only operation, nonce verified in actual AJAX handlers) 194 $ajax_action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : ''; 195 // phpcs:enable WordPress.Security.NonceVerification.Missing 196 if ( strpos( $ajax_action, 'opti_behavior' ) === 0 || strpos( $ajax_action, 'optibehavior' ) === 0 ) { 197 $is_opti_behavior_ajax = true; 198 } 199 } 200 201 if ( ! in_array( $current_page, $opti_behavior_pages, true ) && ! $is_opti_behavior_ajax ) { 190 202 return $override; // Return original for non-plugin pages 191 203 } … … 214 226 215 227 // If a non-English language is selected, load the custom .mo file 216 $custom_mofile = dirname( __FILE__ ) . '/languages/opti-behavior-' . $selected_language . '.mo'; 228 // Determine the plugin directory based on the domain 229 if ( $domain === 'opti-behavior-pro' ) { 230 $plugin_dir = dirname( __FILE__ ) . '/../opti-behavior-pro'; 231 } else { 232 $plugin_dir = dirname( __FILE__ ); 233 } 234 235 $custom_mofile = $plugin_dir . '/languages/' . $domain . '-' . $selected_language . '.mo'; 217 236 218 237 // Get debug manager if available … … 220 239 $core = Opti_Behavior_Heatmap_Core::get_instance(); 221 240 $debug_manager = $core->get_debug_manager(); 222 $debug_manager->log( 'Override load textdomain. Original: ' . $mofile . ', Custom: ' . $custom_mofile . ' (exists: ' . ( file_exists( $custom_mofile ) ? 'yes' : 'no' ) . ')', 'debug', 'i18n' );241 $debug_manager->log( 'Override load textdomain. Domain: ' . $domain . ', Original: ' . $mofile . ', Custom: ' . $custom_mofile . ' (exists: ' . ( file_exists( $custom_mofile ) ? 'yes' : 'no' ) . ')', 'debug', 'i18n' ); 223 242 } 224 243 … … 236 255 $core = Opti_Behavior_Heatmap_Core::get_instance(); 237 256 $debug_manager = $core->get_debug_manager(); 238 $debug_manager->log( 'Successfully loaded custom .mo file with ' . count( $mo->entries ) . ' translations', 'info', 'i18n' );257 $debug_manager->log( 'Successfully loaded custom .mo file for domain "' . $domain . '" with ' . count( $mo->entries ) . ' translations', 'info', 'i18n' ); 239 258 } 240 259 241 260 return true; // Tell WordPress we handled the loading 261 } else { 262 // Log failure 263 if ( class_exists( 'Opti_Behavior_Heatmap_Core' ) ) { 264 $core = Opti_Behavior_Heatmap_Core::get_instance(); 265 $debug_manager = $core->get_debug_manager(); 266 $debug_manager->log( 'Failed to import .mo file for domain "' . $domain . '": ' . $custom_mofile, 'error', 'i18n' ); 267 } 242 268 } 243 269 } -
opti-behavior/trunk/admin/class-opti-behavior-heatmap-ajax-handler.php
r3401441 r3408429 81 81 add_action( 'wp_ajax_optibehavior_top_users', array( $this, 'ajax_top_users' ) ); 82 82 add_action( 'wp_ajax_optibehavior_backfill_pageview_times', array( $this, 'ajax_backfill_pageview_times' ) ); 83 84 // Heartbeat handler for session duration and scroll depth updates 85 add_action( 'wp_ajax_opti_behavior_heatmap_heartbeat', array( $this, 'ajax_heartbeat' ) ); 86 add_action( 'wp_ajax_nopriv_opti_behavior_heatmap_heartbeat', array( $this, 'ajax_heartbeat' ) ); 83 87 84 88 // Support form email handler … … 475 479 476 480 // Create new session with referrer and UTM data 481 // Capture WordPress user ID if user is logged in 482 $user_id = is_user_logged_in() ? get_current_user_id() : null; 483 477 484 $session_data = array( 478 485 'id' => $session_id, 479 486 'visitor_id' => $visitor_id, 487 'user_id' => $user_id, 480 488 'start_time' => current_time( 'mysql' ), 481 489 'end_time' => current_time( 'mysql' ), … … 488 496 'utm_term' => ! empty( $utm_term ) ? $utm_term : null, 489 497 'utm_content' => ! empty( $utm_content ) ? $utm_content : null, 498 'is_bounce' => 1, 490 499 ); 491 500 … … 493 502 "{$wpdb->prefix}optibehavior_sessions", 494 503 $session_data, 495 array( '%s', '%s', '% s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )504 array( '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d' ) 496 505 ); 497 506 … … 645 654 } 646 655 647 // Create new pageview with default scroll depth of 50% 648 // (This simulates user scrolling halfway down the page) 656 // Create new pageview with scroll depth of 0 (will be updated by JavaScript tracking) 649 657 $wpdb->insert( 650 658 "{$wpdb->prefix}optibehavior_pageviews", … … 656 664 'title' => $title, 657 665 'view_time' => current_time( 'mysql' ), 658 'scroll_depth' => 50,666 'scroll_depth' => 0, 659 667 ), 660 668 array( '%s', '%s', '%d', '%s', '%s', '%s', '%d' ) … … 927 935 928 936 // Build date condition directly in SQL based on whitelisted period 929 $allowed_periods = array( 'today', 'yesterday', 'last7days', 'last30days', 'thismonth' );937 $allowed_periods = array( 'today', 'yesterday', 'last7days', 'last30days', 'thismonth', 'custom' ); 930 938 if ( ! in_array( $period, $allowed_periods, true ) ) { 939 $period = 'last7days'; 940 } 941 942 // Validate custom dates if period is custom 943 if ( $period === 'custom' && ( empty( $start_date ) || empty( $end_date ) ) ) { 931 944 $period = 'last7days'; 932 945 } … … 939 952 v.device_type, 940 953 v.last_visit, 954 MAX(s.user_id) as user_id, 941 955 COUNT(DISTINCT s.id) as session_count, 942 956 COALESCE(SUM(s.duration), 0) as total_duration, … … 961 975 $sql .= "s.start_time >= DATE_FORMAT(NOW(), '%Y-%m-01')"; 962 976 break; 977 case 'custom': 978 // Use prepared statement for custom dates 979 $sql .= $wpdb->prepare( 's.start_time >= %s AND s.start_time <= DATE_ADD(%s, INTERVAL 1 DAY)', $start_date, $end_date ); 980 break; 963 981 case 'last7days': 964 982 default: … … 967 985 } 968 986 987 // Add visitor date filter based on same period 988 $visitor_date_filter = ''; 989 switch ( $period ) { 990 case 'today': 991 $visitor_date_filter = ' AND v.last_visit >= CURDATE()'; 992 break; 993 case 'yesterday': 994 $visitor_date_filter = ' AND v.last_visit >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND v.last_visit < CURDATE()'; 995 break; 996 case 'last30days': 997 $visitor_date_filter = ' AND v.last_visit >= DATE_SUB(NOW(), INTERVAL 30 DAY)'; 998 break; 999 case 'thismonth': 1000 $visitor_date_filter = " AND v.last_visit >= DATE_FORMAT(NOW(), '%Y-%m-01')"; 1001 break; 1002 case 'custom': 1003 $visitor_date_filter = $wpdb->prepare( ' AND v.last_visit >= %s AND v.last_visit <= DATE_ADD(%s, INTERVAL 1 DAY)', $start_date, $end_date ); 1004 break; 1005 case 'last7days': 1006 default: 1007 $visitor_date_filter = ' AND v.last_visit >= DATE_SUB(NOW(), INTERVAL 7 DAY)'; 1008 break; 1009 } 1010 1011 969 1012 $sql .= " 970 1013 LEFT JOIN {$wpdb->prefix}optibehavior_pageviews pv ON s.id = pv.session_id 971 WHERE v.last_visit >= DATE_SUB(NOW(), INTERVAL 30 DAY) 1014 WHERE 1=1"; 1015 $sql .= $visitor_date_filter; 1016 $sql .= " 972 1017 GROUP BY v.id, v.country_name, v.country, v.device_type, v.last_visit 973 1018 HAVING session_count > 0 974 1019 ORDER BY session_count DESC, total_duration DESC 975 LIMIT 10 ";976 977 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- SQL built from whitelisted period values only, no user input interpolated1020 LIMIT 100"; 1021 1022 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- SQL built from whitelisted period values only, custom dates use $wpdb->prepare(), no user input interpolated 978 1023 $results = $wpdb->get_results( $sql ); 1024 1025 // Debug: Check sessions table for user_id values 1026 $debug_manager = $this->core->get_debug_manager(); 1027 if ( $debug_manager->is_php_debug_enabled() ) { 1028 $debug_sessions = $wpdb->get_results( "SELECT visitor_id, user_id, start_time FROM {$wpdb->prefix}optibehavior_sessions WHERE visitor_id LIKE 'visitor_1764698224486%' ORDER BY start_time DESC LIMIT 3" ); 1029 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging controlled by settings 1030 error_log( 'Sessions for hamdo visitor: ' . print_r( $debug_sessions, true ) ); 1031 1032 // Debug: Log the SQL query and first result 1033 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1034 error_log( 'Top Users SQL: ' . $sql ); 1035 if ( ! empty( $results ) ) { 1036 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1037 error_log( 'First result username: ' . ( isset( $results[0]->username ) ? $results[0]->username : 'NULL' ) ); 1038 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1039 error_log( 'First result visitor_id: ' . $results[0]->visitor_id ); 1040 } 1041 } 979 1042 980 1043 // Format the results for frontend consumption with correct field names … … 994 1057 } 995 1058 996 // Create visitor short ID for display 997 $visitor_short = substr( $row->visitor_id, 0, 8 ) . '...'; 1059 // Create visitor display - show username for logged-in users, visitor ID otherwise 1060 // Get username for logged-in users 1061 $username = null; 1062 if ( ! empty( $row->user_id ) && $row->user_id > 0 ) { 1063 $user = get_user_by( 'id', $row->user_id ); 1064 if ( $user ) { 1065 $username = $user->display_name; 1066 } 1067 } 1068 $visitor_short = ! empty( $username ) ? $username : substr( $row->visitor_id, 0, 8 ) . '...'; 998 1069 999 1070 $formatted_results[] = array( … … 1001 1072 'visitor_id' => $row->visitor_id, 1002 1073 'visitor_short' => $visitor_short, 1074 'display_name' => $username, 1075 'user_id' => ! empty( $row->user_id ) ? intval( $row->user_id ) : null, 1076 'profile_url' => ! empty( $username ) ? admin_url( 'user-edit.php?user_id=' . $row->user_id ) : '', 1003 1077 'country' => ( $row->country_name ?: ( ( $row->country && strtoupper($row->country) !== 'UN' ) ? $this->get_country_name( strtoupper($row->country) ) : 'Unknown' ) ), 1004 1078 'country_name' => ( $row->country_name ?: ( ( $row->country && strtoupper($row->country) !== 'UN' ) ? $this->get_country_name( strtoupper($row->country) ) : 'Unknown' ) ), … … 1021 1095 } 1022 1096 1097 if ( $debug_manager->is_php_debug_enabled() ) { 1098 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1099 error_log( 'Formatted results count: ' . count( $formatted_results ) ); 1100 if ( ! empty( $formatted_results ) ) { 1101 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1102 error_log( 'First formatted result visitor_short: ' . $formatted_results[0]['visitor_short'] ); 1103 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1104 error_log( 'First formatted result display_name: ' . ( $formatted_results[0]['display_name'] ?? 'NULL' ) ); 1105 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging controlled by settings 1106 error_log( 'First formatted result user_id: ' . ( $formatted_results[0]['user_id'] ?? 'NULL' ) ); 1107 } 1108 } 1023 1109 wp_send_json_success( array( 'items' => $formatted_results ) ); 1024 1110 } … … 1570 1656 'browser' => isset( $data['device']['browser'] ) ? $data['device']['browser'] : 'unknown', 1571 1657 'os' => isset( $data['device']['os'] ) ? $data['device']['os'] : 'unknown', 1658 'screen_width' => isset( $data['screen_width'] ) ? intval( $data['screen_width'] ) : null, 1659 'screen_height' => isset( $data['screen_height'] ) ? intval( $data['screen_height'] ) : null, 1572 1660 'country' => $country, 1573 1661 'country_name' => $country_name, … … 1584 1672 1585 1673 if ( $existing_visitor ) { 1586 // Update existing visitor with location data if available1674 // Update existing visitor with device and location data 1587 1675 $update_data = array( 1588 'last_visit' => current_time( 'mysql' ), 1589 'visit_count' => $existing_visitor->visit_count + 1, 1676 'last_visit' => current_time( 'mysql' ), 1677 'visit_count' => $existing_visitor->visit_count + 1, 1678 'device_type' => isset( $data['device']['deviceType'] ) ? $data['device']['deviceType'] : 'unknown', 1679 'browser' => isset( $data['device']['browser'] ) ? $data['device']['browser'] : 'unknown', 1680 'os' => isset( $data['device']['os'] ) ? $data['device']['os'] : 'unknown', 1681 'screen_width' => isset( $data['screen_width'] ) ? intval( $data['screen_width'] ) : null, 1682 'screen_height' => isset( $data['screen_height'] ) ? intval( $data['screen_height'] ) : null, 1590 1683 ); 1591 $update_format = array( '%s', '%d' );1684 $update_format = array( '%s', '%d', '%s', '%s', '%s', '%d', '%d' ); 1592 1685 1593 1686 // Add location data to update if available … … 1613 1706 "{$wpdb->prefix}optibehavior_visitors", 1614 1707 $visitor_data, 1615 array( '%s', '%s', '%s', '%d', '%s', '%s', '%s', '% s', '%s', '%s', '%s', '%s' )1708 array( '%s', '%s', '%s', '%d', '%s', '%s', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%s' ) 1616 1709 ); 1617 1710 } … … 1641 1734 } else { 1642 1735 // Insert new session 1736 // Capture WordPress user ID if user is logged in 1737 $user_id = is_user_logged_in() ? get_current_user_id() : null; 1738 1643 1739 $session_data = array( 1644 1740 'id' => $session_id, 1645 1741 'visitor_id' => $visitor_id, 1742 'user_id' => $user_id, 1646 1743 'start_time' => current_time( 'mysql' ), 1647 1744 'referrer' => isset( $data['referrer'] ) ? $data['referrer'] : '', 1648 1745 'entry_page' => $session_url, 1649 1746 'ip' => $this->get_client_ip(), 1747 'is_bounce' => 1, 1650 1748 ); 1651 1749 … … 1653 1751 "{$wpdb->prefix}optibehavior_sessions", 1654 1752 $session_data, 1655 array( '%s', '%s', '% s', '%s', '%s', '%s' )1753 array( '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%d' ) 1656 1754 ); 1657 1755 $debug_manager->log( 'New session created: ' . $session_id, 'debug', 'ajax' ); … … 1731 1829 // Handle click events for heatmaps 1732 1830 if ( $event['type'] === 'click' && isset( $event['data']['x'], $event['data']['y'] ) ) { 1831 // A click indicates engagement - session is not a bounce 1832 $wpdb->update( 1833 "{$wpdb->prefix}optibehavior_sessions", 1834 array( 'is_bounce' => 0 ), 1835 array( 'id' => $session_id ), 1836 array( '%d' ), 1837 array( '%s' ) 1838 ); 1839 $debug_manager->log( 'Bounce status updated to 0 due to click engagement for session: ' . $session_id, 'debug', 'ajax' ); 1840 1733 1841 $current_url = isset( $event['data']['url'] ) ? $event['data']['url'] : ( isset( $data['url'] ) ? $data['url'] : '' ); 1734 1842 if ( empty( $current_url ) ) { … … 1843 1951 } 1844 1952 1953 // If user scrolled more than 25%, consider it engagement - not a bounce 1954 if ( $scroll_depth > 25 ) { 1955 $wpdb->update( 1956 "{$wpdb->prefix}optibehavior_sessions", 1957 array( 'is_bounce' => 0 ), 1958 array( 'id' => $session_id ), 1959 array( '%d' ), 1960 array( '%s' ) 1961 ); 1962 $debug_manager->log( 'Bounce status updated to 0 due to scroll engagement (' . intval( $scroll_depth ) . '%) for session: ' . $session_id, 'debug', 'ajax' ); 1963 } 1964 1845 1965 // Update the pageview record with the latest scroll depth 1846 1966 $wpdb->update( … … 1896 2016 ) ); 1897 2017 1898 // It's a bounce if only one page was viewed 1899 if ( $pageview_count <= 1 ) { 2018 // It's a bounce if only one page was viewed AND no prior engagement was detected 2019 // Don't override is_bounce = 0 that was set by scroll/click handlers 2020 // First, check current bounce status to preserve engagement flags 2021 $current_bounce = $wpdb->get_var( $wpdb->prepare( 2022 "SELECT is_bounce FROM {$wpdb->prefix}optibehavior_sessions WHERE id = %s", 2023 $session_id 2024 ) ); 2025 2026 if ( $pageview_count <= 1 && intval( $current_bounce ) !== 0 ) { 1900 2027 $is_bounce = 1; 2028 } else if ( intval( $current_bounce ) === 0 ) { 2029 // Preserve engagement flag - user scrolled > 25% or clicked 2030 $is_bounce = 0; 1901 2031 } 1902 2032 … … 2267 2397 } 2268 2398 2399 /** 2400 * AJAX handler for heartbeat updates (session duration and scroll depth) 2401 * 2402 * @since 1.0.6.7 2403 */ 2404 public function ajax_heartbeat() { 2405 $debug_manager = $this->core->get_debug_manager(); 2406 $debug_manager->log( 'AJAX request received: opti_behavior_heatmap_heartbeat', 'debug', 'ajax' ); 2407 2408 // Verify nonce for security 2409 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'opti_behavior_heatmap_nonce' ) ) { 2410 $debug_manager->log( 'Heartbeat request failed: invalid nonce', 'warning', 'ajax' ); 2411 wp_send_json_error( __( 'Invalid nonce', 'opti-behavior' ) ); 2412 } 2413 2414 global $wpdb; 2415 2416 $session_id = isset( $_POST['session_id'] ) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : ''; 2417 $visitor_id = isset( $_POST['visitor_id'] ) ? sanitize_text_field( wp_unslash( $_POST['visitor_id'] ) ) : ''; 2418 $url = isset( $_POST['url'] ) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : ''; 2419 $title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : ''; 2420 $duration = isset( $_POST['duration'] ) ? intval( $_POST['duration'] ) : 0; 2421 $scroll_depth = isset( $_POST['scroll_depth'] ) ? intval( $_POST['scroll_depth'] ) : 0; 2422 2423 if ( empty( $session_id ) || empty( $visitor_id ) ) { 2424 $debug_manager->log( 'Heartbeat request failed: missing session_id or visitor_id', 'warning', 'ajax' ); 2425 wp_send_json_error( __( 'Invalid session', 'opti-behavior' ) ); 2426 } 2427 2428 $debug_manager->log( "Heartbeat update - Session: $session_id, Duration: {$duration}s, Scroll: {$scroll_depth}%", 'info', 'ajax' ); 2429 2430 // Ensure session exists before updating 2431 $session_exists = $wpdb->get_var( $wpdb->prepare( 2432 "SELECT id FROM {$wpdb->prefix}optibehavior_sessions WHERE id = %s", 2433 $session_id 2434 ) ); 2435 2436 if ( ! $session_exists ) { 2437 // Session doesn't exist yet, create it using ensure_session_exists 2438 $this->ensure_session_exists( $session_id, $visitor_id, $url, '', null, null ); 2439 } 2440 2441 // Update session duration and end_time 2442 $update_data = array( 2443 'end_time' => current_time( 'mysql' ), 2444 'duration' => $duration, 2445 ); 2446 $format_array = array( '%s', '%d' ); 2447 2448 // If user scrolled more than 25%, consider it engagement - not a bounce 2449 if ( $scroll_depth > 25 ) { 2450 $update_data['is_bounce'] = 0; 2451 $format_array[] = '%d'; 2452 $debug_manager->log( 'Bounce status updated to 0 due to scroll engagement (' . intval( $scroll_depth ) . '%) in heartbeat for session: ' . $session_id, 'debug', 'ajax' ); 2453 } 2454 2455 $result = $wpdb->update( 2456 "{$wpdb->prefix}optibehavior_sessions", 2457 $update_data, 2458 array( 'id' => $session_id ), 2459 $format_array, 2460 array( '%s' ) 2461 ); 2462 2463 $debug_manager->log( "Session update result: " . ($result !== false ? 'success' : 'failed') . ", rows affected: " . ($result ? $result : '0'), 'info', 'ajax' ); 2464 2465 // Update scroll depth in pageviews table 2466 $analytics = $this->core->get_analytics(); 2467 $page_id = $analytics->get_or_create_page_id( $url, $title ); 2468 2469 // Ensure pageview exists before updating scroll depth 2470 $this->ensure_pageview_exists( $session_id, $visitor_id, $page_id, $url, $title ); 2471 2472 $scroll_result = $wpdb->query( $wpdb->prepare( 2473 "UPDATE {$wpdb->prefix}optibehavior_pageviews 2474 SET scroll_depth = GREATEST(scroll_depth, %d) 2475 WHERE session_id = %s AND page_id = %d", 2476 $scroll_depth, 2477 $session_id, 2478 $page_id 2479 ) ); 2480 2481 $debug_manager->log( "Scroll depth update result: rows affected: " . $wpdb->rows_affected, 'info', 'ajax' ); 2482 $debug_manager->log( "Heartbeat completed - Session duration: {$duration}s, Scroll depth: {$scroll_depth}%", 'info', 'ajax' ); 2483 2484 wp_send_json_success( array( 2485 'status' => 'updated', 2486 'duration' => $duration, 2487 'scroll_depth' => $scroll_depth, 2488 ) ); 2489 } 2490 2269 2491 } -
opti-behavior/trunk/admin/class-opti-behavior-heatmap-dashboard.php
r3406294 r3408429 266 266 'noData' => __( 'No data available', 'opti-behavior' ), 267 267 'error' => __( 'Error loading data', 'opti-behavior' ), 268 // Dashboard widget strings 269 'newVisitors' => __( 'New Visitors', 'opti-behavior' ), 270 'returningVisitors' => __( 'Returning Visitors', 'opti-behavior' ), 271 'totalVisitors' => __( 'Total Visitors', 'opti-behavior' ), 272 'loggedInVisitors' => __( 'Logged In Visitors', 'opti-behavior' ), 273 'newRegistrations' => __( 'New Registrations', 'opti-behavior' ), 274 'homePage' => __( 'Home Page', 'opti-behavior' ), 275 'posts' => __( 'Posts', 'opti-behavior' ), 276 // User intent 277 'lowIntent' => __( 'Low intent', 'opti-behavior' ), 278 'mediumIntent' => __( 'Medium intent', 'opti-behavior' ), 279 'highIntent' => __( 'High intent', 'opti-behavior' ), 280 // Device types 281 'desktop' => __( 'Desktop', 'opti-behavior' ), 282 'mobile' => __( 'Mobile', 'opti-behavior' ), 283 'tablet' => __( 'Tablet', 'opti-behavior' ), 284 'pc' => __( 'PC', 'opti-behavior' ), 285 // Operating systems 286 'windows' => __( 'Windows', 'opti-behavior' ), 287 'chrome' => __( 'Chrome', 'opti-behavior' ), 288 // Empty state messages 289 'noReferrerData' => __( 'No referrer data available', 'opti-behavior' ), 290 'noCountryData' => __( 'No country data available', 'opti-behavior' ), 291 'noScreenResolutionData' => __( 'No screen resolution data available', 'opti-behavior' ), 292 'tryBroadeningDateRange' => __( 'Try broadening the date range or check back later.', 'opti-behavior' ), 293 'noPageData' => __( 'No page data available', 'opti-behavior' ), 294 'noVisitorData' => __( 'No visitor data available', 'opti-behavior' ), 295 'noBrowserData' => __( 'No browser data available', 'opti-behavior' ), 296 'noDeviceData' => __( 'No device data available', 'opti-behavior' ), 297 'dataWillAppear' => __( 'Data will appear as visitors interact with your site.', 'opti-behavior' ), 298 'noDataYet' => __( 'No data yet', 'opti-behavior' ), 268 299 ); 269 300 } … … 1286 1317 1287 1318 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Static query with no user input 1288 $results = $wpdb->get_results( $query);1319 $results = $wpdb->get_results( $query ); 1289 1320 } 1290 1321 … … 2696 2727 WHERE id IN ($placeholders)"; 2697 2728 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Dynamic placeholders are built safely with array_fill and implode, table prefix is from wpdb 2698 $pages_info = $wpdb->get_results( $wpdb->prepare( 2699 $query, 2700 ...$page_ids 2701 ), OBJECT_K ); 2729 $pages_info = $wpdb->get_results( 2730 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $query variable with dynamic placeholders 2731 $wpdb->prepare( 2732 $query, 2733 ...$page_ids 2734 ), 2735 OBJECT_K 2736 ); 2702 2737 } else { 2703 2738 $pages_info = array(); -
opti-behavior/trunk/admin/class-opti-behavior-heatmap-post-metabox.php
r3406294 r3408429 370 370 public function ajax_post_analytics() { 371 371 if ( ! isset( $_POST['post_id'] ) ) { 372 wp_send_json_error( array( 'message' => 'No post_id provided') );372 wp_send_json_error( array( 'message' => esc_html__( 'No post_id provided', 'opti-behavior' ) ) ); 373 373 } 374 374 … … 377 377 378 378 if ( ! current_user_can( 'edit_post', $post_id ) ) { 379 wp_send_json_error( array( 'message' => 'Permission denied' ) ); 379 wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'opti-behavior' ) ) ); 380 } 381 382 // Check if post is published - only show analytics for published posts 383 $post_status = get_post_status( $post_id ); 384 if ( 'publish' !== $post_status ) { 385 wp_send_json_error( array( 386 'message' => esc_html__( 'Post not published yet', 'opti-behavior' ), 387 'not_published' => true, 388 'post_status' => $post_status 389 ) ); 380 390 } 381 391 … … 383 393 $url = get_permalink( $post_id ); 384 394 if ( ! $url ) { 385 wp_send_json_error( array( 'message' => 'No permalink found') );395 wp_send_json_error( array( 'message' => esc_html__( 'No permalink found', 'opti-behavior' ) ) ); 386 396 } 387 397 … … 762 772 public function ajax_post_analytics_chart() { 763 773 if ( ! isset( $_POST['post_id'] ) ) { 764 wp_send_json_error( array( 'message' => 'No post_id provided') );774 wp_send_json_error( array( 'message' => esc_html__( 'No post_id provided', 'opti-behavior' ) ) ); 765 775 } 766 776 … … 769 779 770 780 if ( ! current_user_can( 'edit_post', $post_id ) ) { 771 wp_send_json_error( array( 'message' => 'Permission denied' ) ); 781 wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'opti-behavior' ) ) ); 782 } 783 784 // Check if post is published 785 $post_status = get_post_status( $post_id ); 786 if ( 'publish' !== $post_status ) { 787 wp_send_json_success( array( 788 'labels' => array(), 789 'total_visitors' => array(), 790 'desktop_visitors' => array(), 791 'mobile_visitors' => array(), 792 'desktop_events' => array(), 793 'mobile_events' => array(), 794 'group' => '%Y-%m-%d', 795 ) ); 772 796 } 773 797 … … 775 799 $url = get_permalink( $post_id ); 776 800 if ( ! $url ) { 777 wp_send_json_error( array( 'message' => 'No permalink found') );801 wp_send_json_error( array( 'message' => esc_html__( 'No permalink found', 'opti-behavior' ) ) ); 778 802 } 779 803 … … 1125 1149 } 1126 1150 1151 // Check if post is published 1152 $post_status = get_post_status( $post_id ); 1153 if ( 'publish' !== $post_status ) { 1154 wp_send_json_success( array() ); 1155 } 1156 1127 1157 global $wpdb; 1128 1158 $url = get_permalink( $post_id ); … … 1199 1229 if ( ! current_user_can( 'edit_post', $post_id ) ) { 1200 1230 wp_send_json_error(); 1231 } 1232 1233 // Check if post is published 1234 $post_status = get_post_status( $post_id ); 1235 if ( 'publish' !== $post_status ) { 1236 wp_send_json_success( array() ); 1201 1237 } 1202 1238 … … 1351 1387 } 1352 1388 1389 // Check if post is published 1390 $post_status = get_post_status( $post_id ); 1391 if ( 'publish' !== $post_status ) { 1392 wp_send_json_success( array() ); 1393 } 1394 1353 1395 global $wpdb; 1354 1396 $url = get_permalink( $post_id ); … … 1400 1442 if ( ! current_user_can( 'edit_post', $post_id ) ) { 1401 1443 wp_send_json_error(); 1444 } 1445 1446 // Check if post is published 1447 $post_status = get_post_status( $post_id ); 1448 if ( 'publish' !== $post_status ) { 1449 wp_send_json_success( array() ); 1402 1450 } 1403 1451 … … 1453 1501 } 1454 1502 1503 // Check if post is published 1504 $post_status = get_post_status( $post_id ); 1505 if ( 'publish' !== $post_status ) { 1506 wp_send_json_success( array() ); 1507 } 1508 1455 1509 global $wpdb; 1456 1510 $url = get_permalink( $post_id ); -
opti-behavior/trunk/admin/recordings-upgrade-page.php
r3401441 r3408429 64 64 65 65 <a href="https://optiuser.com/" target="_blank" rel="noopener noreferrer" class="button button-primary button-hero"> 66 <i data-lucide=" download"></i>67 <?php esc_html_e( ' Download PRO Version', 'opti-behavior' ); ?>66 <i data-lucide="clock"></i> 67 <?php esc_html_e( 'Coming Soon', 'opti-behavior' ); ?> 68 68 </a> 69 69 -
opti-behavior/trunk/assets/css/dashboard_styles.css
r3406294 r3408429 2438 2438 margin-bottom: 8px; 2439 2439 } 2440 2441 /* Logged-in User Row Highlighting */ 2442 .tu-logged-in-user { 2443 background-color: rgba(16, 185, 129, 0.08) !important; 2444 border-left: 3px solid #10b981 !important; 2445 } 2446 2447 .tu-logged-in-user:hover { 2448 background-color: rgba(16, 185, 129, 0.15) !important; 2449 } 2450 2451 /* Make the row stand out more on hover */ 2452 .tu-logged-in-user td { 2453 position: relative; 2454 } -
opti-behavior/trunk/assets/css/recordings-upgrade.css
r3401441 r3408429 229 229 display: inline-flex; 230 230 align-items: center; 231 gap: 12px; 232 font-size: 16px; 233 padding: 14px 32px; 231 justify-content: center; 232 gap: 10px; 233 font-size: 17px; 234 padding: 16px 40px; 234 235 height: auto; 235 236 line-height: 1.5; … … 239 240 background: #2271b1; 240 241 border-color: #2271b1; 242 text-decoration: none; 243 box-shadow: 0 4px 12px rgba(34, 113, 177, 0.2); 241 244 } 242 245 … … 251 254 width: 22px; 252 255 height: 22px; 256 flex-shrink: 0; 257 margin-right: 4px; 253 258 } 254 259 -
opti-behavior/trunk/assets/js/dashboard.js
r3406294 r3408429 183 183 184 184 // Prepare device types array with all three types 185 const i18n = window.opti_behaviorData?.strings || {}; 186 const deviceLabels = { 187 'Desktop': i18n.desktop || 'Desktop', 188 'Mobile': i18n.mobile || 'Mobile', 189 'Tablet': i18n.tablet || 'Tablet' 190 }; 185 191 const deviceTypes = ['Desktop', 'Mobile', 'Tablet'].map(name => { 186 192 const item = data.find(d => d.name === name); 187 193 return { 188 name: name, 194 name: deviceLabels[name], 195 rawName: name, 189 196 count: item ? (item.count || 0) : 0, 190 197 prevCount: item ? (item.prevCount || 0) : 0, … … 239 246 240 247 // Prepare chart data 241 const deviceTypes = ['Desktop', 'Mobile', 'Tablet']; 242 const chartData = deviceTypes.map(name => { 248 const i18n = window.opti_behaviorData?.strings || {}; 249 const deviceTypeKeys = ['Desktop', 'Mobile', 'Tablet']; 250 const deviceLabels = { 251 'Desktop': i18n.desktop || 'Desktop', 252 'Mobile': i18n.mobile || 'Mobile', 253 'Tablet': i18n.tablet || 'Tablet' 254 }; 255 const chartData = deviceTypeKeys.map(name => { 243 256 const item = deviceData.find(d => d.name === name); 244 257 return item ? (item.count || 0) : 0; 245 258 }); 259 const chartLabels = deviceTypeKeys.map(name => deviceLabels[name]); 246 260 247 261 // Check if we have any data … … 255 269 // Show empty state 256 270 if (window.optibehavior_showEmptyStateForCanvas) { 257 window.optibehavior_showEmptyStateForCanvas('device-types-pie', 'device', 'No device data available'); 271 const emptyMsg = i18n.noDeviceData || 'No device data available'; 272 window.optibehavior_showEmptyStateForCanvas('device-types-pie', 'device', emptyMsg); 258 273 } 259 274 return; … … 275 290 } 276 291 277 const chartColors = deviceType s.map(name => DEVICE_COLORS[name]);292 const chartColors = deviceTypeKeys.map(name => DEVICE_COLORS[name]); 278 293 279 294 // Destroy existing chart if it exists … … 285 300 type: 'doughnut', 286 301 data: { 287 labels: deviceTypes,302 labels: chartLabels, 288 303 datasets: [{ 289 304 data: chartData, … … 1458 1473 1459 1474 // Create rows for each intent type 1475 const i18n = window.opti_behaviorData?.strings || {}; 1460 1476 const intentTypes = [ 1461 { name: 'Low intent', count: lowSessions, percentage: lowPct, prevCount: prevLowSessions, color: '#e91e63' },1462 { name: 'Medium intent', count: mediumSessions, percentage: mediumPct, prevCount: prevMediumSessions, color: '#7c3aed' },1463 { name: 'High intent', count: highSessions, percentage: highPct, prevCount: prevHighSessions, color: '#f59e0b' }1477 { name: i18n.lowIntent || 'Low intent', count: lowSessions, percentage: lowPct, prevCount: prevLowSessions, color: '#e91e63' }, 1478 { name: i18n.mediumIntent || 'Medium intent', count: mediumSessions, percentage: mediumPct, prevCount: prevMediumSessions, color: '#7c3aed' }, 1479 { name: i18n.highIntent || 'High intent', count: highSessions, percentage: highPct, prevCount: prevHighSessions, color: '#f59e0b' } 1464 1480 ]; 1465 1481 … … 1501 1517 const data = []; 1502 1518 const backgroundColors = ['#e91e63', '#7c3aed', '#f59e0b']; // low, medium, high 1519 const i18n = window.opti_behaviorData?.strings || {}; 1503 1520 1504 1521 if (lowSessions > 0) { 1505 labels.push( 'Low intent');1522 labels.push(i18n.lowIntent || 'Low intent'); 1506 1523 data.push(lowSessions); 1507 1524 } 1508 1525 if (mediumSessions > 0) { 1509 labels.push( 'Medium intent');1526 labels.push(i18n.mediumIntent || 'Medium intent'); 1510 1527 data.push(mediumSessions); 1511 1528 } 1512 1529 if (highSessions > 0) { 1513 labels.push( 'High intent');1530 labels.push(i18n.highIntent || 'High intent'); 1514 1531 data.push(highSessions); 1515 1532 } … … 1627 1644 1628 1645 // Create rows for each visitor type 1646 const i18n = window.opti_behaviorData?.strings || {}; 1629 1647 const visitorTypes = [ 1630 { name: 'New Visitors', count: newCount, percentage: newPct, prevCount: prevNewCount, color: '#10B981' },1631 { name: 'Returning Visitors', count: returningCount, percentage: returningPct, prevCount: prevReturningCount, color: '#6366F1' }1648 { name: i18n.newVisitors || 'New Visitors', count: newCount, percentage: newPct, prevCount: prevNewCount, color: '#10B981' }, 1649 { name: i18n.returningVisitors || 'Returning Visitors', count: returningCount, percentage: returningPct, prevCount: prevReturningCount, color: '#6366F1' } 1632 1650 ]; 1633 1651 … … 1703 1721 if (existingChart) existingChart.destroy(); 1704 1722 1723 // Get i18n strings 1724 const i18n = window.opti_behaviorData?.strings || {}; 1725 1705 1726 // Create Chart.js donut chart 1706 1727 new Chart(ctx, { 1707 1728 type: 'doughnut', 1708 1729 data: { 1709 labels: [ 'New Visitors','Returning Visitors'],1730 labels: [i18n.newVisitors || 'New Visitors', i18n.returningVisitors || 'Returning Visitors'], 1710 1731 datasets: [{ 1711 1732 label: 'Visitors', … … 1767 1788 const newRegPct = total > 0 ? Math.round((newRegistrations / total) * 100) : 0; 1768 1789 1790 const i18n = window.opti_behaviorData?.strings || {}; 1769 1791 const visitorTypes = [ 1770 1792 { 1771 name: 'Total Visitors',1793 name: i18n.totalVisitors || 'Total Visitors', 1772 1794 count: totalVisitors, 1773 1795 percentage: totalPct, … … 1776 1798 }, 1777 1799 { 1778 name: 'Logged In Visitors',1800 name: i18n.loggedInVisitors || 'Logged In Visitors', 1779 1801 count: loggedInVisitors, 1780 1802 percentage: loggedInPct, … … 1783 1805 }, 1784 1806 { 1785 name: 'New Registrations',1807 name: i18n.newRegistrations || 'New Registrations', 1786 1808 count: newRegistrations, 1787 1809 percentage: newRegPct, … … 2225 2247 if (!topPages || !topPages.length) { 2226 2248 // Show empty state 2249 const i18n = window.opti_behaviorData?.strings || {}; 2227 2250 container.innerHTML = ` 2228 2251 <div class="optibehavior-empty-state is-visible"> 2229 2252 <i data-lucide="file-text" style="width: 48px; height: 48px; color: #9ca3af; stroke-width: 1.5;"></i> 2230 <div class="optibehavior-empty-title"> No page data available</div>2231 <div class="optibehavior-empty-sub"> Try broadening the date range or check back later.</div>2253 <div class="optibehavior-empty-title">${i18n.noPageData || 'No page data available'}</div> 2254 <div class="optibehavior-empty-sub">${i18n.tryBroadeningDateRange || 'Try broadening the date range or check back later.'}</div> 2232 2255 </div> 2233 2256 `; … … 2352 2375 // Show empty state 2353 2376 if (window.optibehavior_showEmptyStateForCanvas) { 2354 window.optibehavior_showEmptyStateForCanvas('sessions-chart', 'sessions','No visitor data available');2377 const i18n = window.opti_behaviorData?.strings || {}; window.optibehavior_showEmptyStateForCanvas('sessions-chart', 'sessions', i18n.noVisitorData || 'No visitor data available'); 2355 2378 } 2356 2379 return; … … 2430 2453 emptyState.className = 'optibehavior-empty-state is-visible'; 2431 2454 emptyState.innerHTML = ` 2455 t const i18n = window.opti_behaviorData?.strings || {}; 2432 2456 <i data-lucide="compass" style="width: 48px; height: 48px; color: #9ca3af; stroke-width: 1.5;"></i> 2433 <div class="optibehavior-empty-title"> No browser data available</div>2434 <div class="optibehavior-empty-sub"> Try broadening the date range or check back later.</div>2457 <div class="optibehavior-empty-title">${i18n.noBrowserData || "No browser data available"}</div> 2458 <div class="optibehavior-empty-sub">${i18n.tryBroadeningDateRange || "Try broadening the date range or check back later."}</div> 2435 2459 `; 2436 2460 widgetContent.appendChild(emptyState); … … 3519 3543 var rows = resp.data.items.map(function(it,idx){ 3520 3544 // Display username with profile link if available, otherwise show visitor ID 3545 var isLoggedIn = it.user_id && it.user_id > 0 && it.display_name; 3521 3546 var visitorDisplay = ''; 3522 if (i t.user_id && it.user_id > 0 && it.display_name) {3547 if (isLoggedIn) { 3523 3548 // User is a logged-in WordPress user - show display name with profile link 3524 3549 visitorDisplay = '<a href="' + esc(it.profile_url||'') + '" target="_blank" rel="noopener" title="View user profile">' + … … 3529 3554 } 3530 3555 3531 return '<tr >'+3556 return '<tr'+ (isLoggedIn ? ' class="tu-logged-in-user"' : '') +'>'+ 3532 3557 '<td class="tu-rank">'+ (idx+1) +'</td>'+ 3533 3558 '<td class="tu-visitor">'+ visitorDisplay +'</td>'+ -
opti-behavior/trunk/assets/js/metabox-analytics.js
r3406294 r3408429 74 74 .then(function(resp) { 75 75 if (!resp || !resp.success || !resp.data) { 76 // Check if it's because the post is not published 77 if (resp && !resp.success && resp.data && resp.data.not_published) { 78 // Show a message indicating the post needs to be published first 79 if (qs('#optibehavior-chart-loading')) qs('#optibehavior-chart-loading').style.display = 'none'; 80 var emptyEl = qs('#optibehavior-empty'); 81 emptyEl.textContent = 'Analytics will be available after this post is published.'; 82 emptyEl.style.display = 'block'; 83 qs('#optibehavior-chart').style.display = 'none'; 84 return; 85 } 76 86 // Hide loading, show empty message 77 87 if (qs('#optibehavior-chart-loading')) qs('#optibehavior-chart-loading').style.display = 'none'; -
opti-behavior/trunk/assets/js/opti-behavior-heatmap-simple.js
r3401441 r3408429 70 70 this.lastSendTime = Date.now(); 71 71 this.sendTimer = null; 72 this.sessionStartTime = Date.now(); 73 this.maxScrollDepth = 0; 74 this.heartbeatTimer = null; 75 this.lastScrollUpdate = 0; 76 // Store session and visitor IDs in memory for reliable access 77 this.sessionId = null; 78 this.visitorId = null; 72 79 } 73 80 … … 87 94 console.log('[Heatmap] start() called'); 88 95 96 // Send initial page view event immediately to create session 97 this.sendPageView(); 98 89 99 // Attach click event listener 90 100 document.addEventListener('click', this.handleClick.bind(this), true); … … 93 103 document.addEventListener('click', this.handleOutboundClick.bind(this), true); 94 104 105 // Attach scroll event listener for scroll depth tracking 106 window.addEventListener('scroll', this.handleScroll.bind(this), { passive: true }); 107 108 // Calculate initial scroll depth 109 this.updateScrollDepth(); 110 95 111 // Start periodic send timer 96 112 this.startSendTimer(); 97 113 114 // Start heartbeat timer to update session duration and scroll depth 115 this.startHeartbeat(); 116 98 117 // Send data before page unload 99 window.addEventListener('beforeunload', this.send Data.bind(this, true));100 101 console.log('[Heatmap] Click tracking started');118 window.addEventListener('beforeunload', this.sendSessionEnd.bind(this)); 119 120 console.log('[Heatmap] Tracking started (clicks, scroll, duration)'); 102 121 }; 103 122 … … 268 287 }; 269 288 289 HeatmapTracker.prototype.handleScroll = function() { 290 this.updateScrollDepth(); 291 }; 292 293 HeatmapTracker.prototype.updateScrollDepth = function() { 294 const scrollTop = window.pageYOffset || document.documentElement.scrollTop; 295 const windowHeight = window.innerHeight; 296 const documentHeight = Math.max( 297 document.documentElement.scrollHeight, 298 document.body.scrollHeight 299 ); 300 301 const currentScrollDepth = Math.min(100, Math.round( 302 ((scrollTop + windowHeight) / documentHeight) * 100 303 )); 304 305 if (currentScrollDepth > this.maxScrollDepth) { 306 this.maxScrollDepth = currentScrollDepth; 307 console.log('[Heatmap] Max scroll depth updated:', this.maxScrollDepth + '%'); 308 } 309 }; 310 270 311 HeatmapTracker.prototype.startSendTimer = function() { 271 312 // Clear existing timer … … 273 314 clearInterval(this.sendTimer); 274 315 } 275 316 276 317 // Start new timer 277 318 this.sendTimer = setInterval(function() { … … 280 321 } 281 322 }.bind(this), this.config.ajax_interval); 323 }; 324 325 HeatmapTracker.prototype.startHeartbeat = function() { 326 // Clear existing timer 327 if (this.heartbeatTimer) { 328 clearInterval(this.heartbeatTimer); 329 } 330 331 // Send heartbeat every 5 seconds to update session duration and scroll depth 332 this.heartbeatTimer = setInterval(function() { 333 this.sendHeartbeat(); 334 }.bind(this), 5000); // 5 seconds 335 }; 336 337 HeatmapTracker.prototype.sendHeartbeat = function() { 338 const sessionDuration = Math.round((Date.now() - this.sessionStartTime) / 1000); 339 340 // Use stored IDs instead of reading cookies 341 if (!this.sessionId || !this.visitorId) { 342 console.log('[Heatmap] Heartbeat skipped - no session/visitor ID'); 343 return; 344 } 345 346 const sessionId = this.sessionId; 347 const visitorId = this.visitorId; 348 349 const formData = new FormData(); 350 formData.append('action', 'opti_behavior_heatmap_heartbeat'); 351 formData.append('nonce', this.config.nonce); 352 formData.append('session_id', sessionId); 353 formData.append('visitor_id', visitorId); 354 formData.append('url', window.location.href); 355 formData.append('title', document.title); 356 formData.append('duration', sessionDuration); 357 formData.append('scroll_depth', this.maxScrollDepth); 358 359 console.log('[Heatmap] Sending heartbeat - Duration:', sessionDuration + 's', 'Scroll:', this.maxScrollDepth + '%'); 360 361 fetch(this.config.ajax_url, { 362 method: 'POST', 363 body: formData, 364 mode: 'same-origin', 365 cache: 'no-cache', 366 keepalive: true 367 }).then(function(response) { 368 return response.json(); 369 }).then(function(data) { 370 console.log('[Heatmap] Heartbeat response:', data); 371 }).catch(function(error) { 372 console.error('[Heatmap] Heartbeat error:', error); 373 }); 374 }; 375 376 HeatmapTracker.prototype.sendSessionEnd = function() { 377 const sessionDuration = Math.round((Date.now() - this.sessionStartTime) / 1000); 378 379 // Use stored IDs instead of reading cookies 380 if (!this.sessionId || !this.visitorId) { 381 return; 382 } 383 384 const sessionId = this.sessionId; 385 const visitorId = this.visitorId; 386 387 const formData = new FormData(); 388 formData.append('action', 'opti_behavior_heatmap_heartbeat'); 389 formData.append('nonce', this.config.nonce); 390 formData.append('session_id', sessionId); 391 formData.append('visitor_id', visitorId); 392 formData.append('url', window.location.href); 393 formData.append('title', document.title); 394 formData.append('duration', sessionDuration); 395 formData.append('scroll_depth', this.maxScrollDepth); 396 397 console.log('[Heatmap] Session end - Duration:', sessionDuration + 's', 'Scroll:', this.maxScrollDepth + '%'); 398 399 // Use sendBeacon for reliable delivery on page unload 400 if (navigator.sendBeacon) { 401 navigator.sendBeacon(this.config.ajax_url, formData); 402 } 282 403 }; 283 404 … … 408 529 } 409 530 }; 410 531 532 /** 533 * Send initial page view to create session immediately on page load 534 * This ensures sessions are tracked even if user doesn't click anything 535 */ 536 /** 537 * Detect browser from user agent 538 */ 539 HeatmapTracker.prototype.detectBrowser = function(userAgent) { 540 if (!userAgent) return 'unknown'; 541 542 if (userAgent.indexOf('Edg') > -1) return 'Edge'; 543 if (userAgent.indexOf('Chrome') > -1 && userAgent.indexOf('Edg') === -1) return 'Chrome'; 544 if (userAgent.indexOf('Safari') > -1 && userAgent.indexOf('Chrome') === -1) return 'Safari'; 545 if (userAgent.indexOf('Firefox') > -1) return 'Firefox'; 546 if (userAgent.indexOf('MSIE') > -1 || userAgent.indexOf('Trident') > -1) return 'Internet Explorer'; 547 if (userAgent.indexOf('Opera') > -1 || userAgent.indexOf('OPR') > -1) return 'Opera'; 548 549 return 'unknown'; 550 }; 551 552 /** 553 * Detect operating system from user agent 554 */ 555 HeatmapTracker.prototype.detectOS = function(userAgent) { 556 if (!userAgent) return 'unknown'; 557 558 if (userAgent.indexOf('Win') > -1) return 'Windows'; 559 if (userAgent.indexOf('Mac') > -1 && userAgent.indexOf('iPhone') === -1 && userAgent.indexOf('iPad') === -1) return 'macOS'; 560 if (userAgent.indexOf('Linux') > -1 && userAgent.indexOf('Android') === -1) return 'Linux'; 561 if (userAgent.indexOf('Android') > -1) return 'Android'; 562 if (userAgent.indexOf('iPhone') > -1 || userAgent.indexOf('iPad') > -1) return 'iOS'; 563 564 return 'unknown'; 565 }; 566 567 /** 568 * Detect device type from user agent and screen width 569 */ 570 HeatmapTracker.prototype.detectDeviceType = function(userAgent, screenWidth) { 571 if (!userAgent) return 'unknown'; 572 573 // Check for mobile indicators in user agent 574 const mobileKeywords = ['Mobile', 'Android', 'iPhone', 'iPad', 'iPod', 'BlackBerry', 'IEMobile', 'Opera Mini']; 575 const isMobileUA = mobileKeywords.some(function(keyword) { 576 return userAgent.indexOf(keyword) > -1; 577 }); 578 579 // Check for tablet indicators 580 const isTablet = userAgent.indexOf('iPad') > -1 || 581 (userAgent.indexOf('Android') > -1 && userAgent.indexOf('Mobile') === -1); 582 583 if (isTablet) return 'tablet'; 584 if (isMobileUA) return 'mobile'; 585 586 // Fallback to screen width detection 587 if (screenWidth <= 768) return 'mobile'; 588 if (screenWidth <= 1024) return 'tablet'; 589 590 return 'desktop'; 591 }; 592 593 HeatmapTracker.prototype.sendPageView = function() { 594 console.log('[Heatmap] sendPageView() called - creating session'); 595 596 // Get session ID from cookie (short-lived, per session) 597 let sessionId = this.getCookie('optibehavior_sid') || this.getCookie('opti_behavior_session_id'); 598 599 // Get visitor ID from localStorage (persistent, survives bounce tracker protection) 600 // Fallback to cookie for backwards compatibility 601 let visitorId = null; 602 try { 603 visitorId = localStorage.getItem('optibehavior_vid') || this.getCookie('optibehavior_vid') || this.getCookie('opti_behavior_visitor_id'); 604 } catch (e) { 605 // localStorage not available (privacy mode, old browsers), fallback to cookie 606 visitorId = this.getCookie('optibehavior_vid') || this.getCookie('opti_behavior_visitor_id'); 607 } 608 609 const trackingConfig = window.optiBehaviorHeatmapConfig || this.config; 610 611 // Generate IDs if they don't exist 612 if (!sessionId) { 613 sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substring(7); 614 document.cookie = 'optibehavior_sid=' + sessionId + '; path=/; max-age=1800; SameSite=Lax'; // 30 min 615 } 616 if (!visitorId) { 617 visitorId = 'visitor_' + Date.now() + '_' + Math.random().toString(36).substring(7); 618 // Store visitor ID in localStorage (immune to bounce tracker protection) 619 try { 620 localStorage.setItem('optibehavior_vid', visitorId); 621 } catch (e) { 622 // localStorage not available, fallback to cookie 623 document.cookie = 'optibehavior_vid=' + visitorId + '; path=/; max-age=31536000; SameSite=Lax'; // 1 year 624 } 625 } 626 627 // Store IDs in memory for reliable access throughout the session 628 this.sessionId = sessionId; 629 this.visitorId = visitorId; 630 631 console.log('[Heatmap] Page view - Session ID:', sessionId); 632 console.log('[Heatmap] Page view - Visitor ID:', visitorId); 633 634 // Detect device information 635 const userAgent = navigator.userAgent; 636 const screenWidth = window.screen.width; 637 const browser = this.detectBrowser(userAgent); 638 const os = this.detectOS(userAgent); 639 const deviceType = this.detectDeviceType(userAgent, screenWidth); 640 641 console.log('[Heatmap] Device info - Browser:', browser, 'OS:', os, 'Type:', deviceType); 642 643 // Build the data object matching server's expected format 644 const data = { 645 action: 'session_start', 646 sessionId: sessionId, 647 visitorId: visitorId, 648 url: window.location.href, 649 title: document.title, 650 userAgent: userAgent, 651 language: navigator.language || navigator.userLanguage || '', 652 screen_width: screenWidth, 653 screen_height: window.screen.height, 654 referrer: document.referrer || trackingConfig.referrer || '', 655 utm_source: trackingConfig.utm_source || '', 656 utm_medium: trackingConfig.utm_medium || '', 657 utm_campaign: trackingConfig.utm_campaign || '', 658 utm_term: trackingConfig.utm_term || '', 659 utm_content: trackingConfig.utm_content || '', 660 entry_page: window.location.href, 661 device: { 662 browser: browser, 663 os: os, 664 deviceType: deviceType 665 } 666 }; 667 668 // Prepare form data 669 const formData = new FormData(); 670 formData.append('action', 'opti_behavior_heatmap_record'); 671 formData.append('nonce', this.config.nonce); 672 formData.append('data', JSON.stringify(data)); 673 674 console.log('[Heatmap] Sending initial session start:', data); 675 676 // Send page view data immediately 677 fetch(this.config.ajax_url, { 678 method: 'POST', 679 body: formData, 680 mode: 'same-origin', 681 cache: 'no-cache' 682 }).then(function(response) { 683 console.log('[Heatmap] Session start response status:', response.status); 684 return response.json(); 685 }).then(function(responseData) { 686 console.log('[Heatmap] Session start response data:', responseData); 687 }).catch(function(error) { 688 console.error('[Heatmap] Session start error:', error); 689 }); 690 }; 691 411 692 })(); 412 693 -
opti-behavior/trunk/includes/class-opti-behavior-heatmap-analytics.php
r3406294 r3408429 865 865 866 866 if ( empty( $path ) ) { 867 return 'Home Page';867 return __( 'Home Page', 'opti-behavior' ); 868 868 } 869 869 -
opti-behavior/trunk/includes/class-opti-behavior-heatmap-core.php
r3399182 r3408429 370 370 wp_register_script( 371 371 'opti-behavior', 372 OPTI_BEHAVIOR_HEATMAP_ASSETS_URL . 'js/opti-behavior-heatmap .min.js',372 OPTI_BEHAVIOR_HEATMAP_ASSETS_URL . 'js/opti-behavior-heatmap-simple.js', 373 373 array( 'jquery', 'opti-behavior-debug' ), 374 374 OPTI_BEHAVIOR_HEATMAP_VERSION, -
opti-behavior/trunk/includes/class-opti-behavior-heatmap-database.php
r3406294 r3408429 414 414 page_views int(5) UNSIGNED DEFAULT 0, 415 415 events_count int(10) UNSIGNED DEFAULT 0, 416 is_bounce tinyint(1) DEFAULT 0,416 is_bounce tinyint(1) DEFAULT 1, 417 417 referrer text DEFAULT NULL, 418 418 utm_source varchar(100) DEFAULT NULL, -
opti-behavior/trunk/includes/class-opti-behavior-heatmap-session.php
r3406294 r3408429 156 156 'entry_page' => isset( $data['entry_page'] ) ? $data['entry_page'] : '', 157 157 'ip' => $this->get_client_ip(), 158 'is_bounce' => 1, 158 159 ); 159 160 … … 161 162 "{$wpdb->prefix}optibehavior_sessions", 162 163 $session_data, 163 array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )164 array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d' ) 164 165 ); 165 166 } -
opti-behavior/trunk/includes/trait-opti-behavior-ai-insights-views.php
r3401441 r3408429 201 201 <form id="opti-behavior-support-form" class="support-form"> 202 202 <div class="form-group"> 203 <label for="support-name"> Your Name</label>203 <label for="support-name"><?php esc_html_e( 'Your Name', 'opti-behavior' ); ?></label> 204 204 <input type="text" id="support-name" name="support_name" required class="form-control" /> 205 205 </div> 206 206 207 207 <div class="form-group"> 208 <label for="support-email"> Your Email</label>208 <label for="support-email"><?php esc_html_e( 'Your Email', 'opti-behavior' ); ?></label> 209 209 <input type="email" id="support-email" name="support_email" value="<?php echo esc_attr( $user_email ); ?>" required class="form-control" /> 210 <small class="form-hint"> We will use this to respond to your message</small>211 </div> 212 213 <div class="form-group"> 214 <label for="support-subject"> Subject</label>210 <small class="form-hint"><?php esc_html_e( 'We will use this to respond to your message', 'opti-behavior' ); ?></small> 211 </div> 212 213 <div class="form-group"> 214 <label for="support-subject"><?php esc_html_e( 'Subject', 'opti-behavior' ); ?></label> 215 215 <input type="text" id="support-subject" name="support_subject" required class="form-control" /> 216 216 </div> 217 217 218 218 <div class="form-group"> 219 <label for="support-message"> Message</label>219 <label for="support-message"><?php esc_html_e( 'Message', 'opti-behavior' ); ?></label> 220 220 <textarea id="support-message" name="support_message" rows="5" required class="form-control"></textarea> 221 221 </div> … … 224 224 <button type="submit" class="feedback-btn primary"> 225 225 <span>📧</span> 226 Send Message226 <?php esc_html_e( 'Send Message', 'opti-behavior' ); ?> 227 227 </button> 228 228 </div> -
opti-behavior/trunk/includes/trait-opti-behavior-dashboard-views.php
r3406294 r3408429 277 277 <svg viewBox='0 0 24 24' fill='none' stroke='#9ca3af' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 3h14a2 2 0 0 1 2 2v14l-4-4H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z'/></svg> 278 278 <div class="optibehavior-empty-title"><?php esc_html_e( 'No page views yet', 'opti-behavior' ); ?></div> 279 <div class="optibehavior-empty-sub"><?php esc_html_e( 'Once visitors view pages, you \'ll see them here.', 'opti-behavior' ); ?></div>279 <div class="optibehavior-empty-sub"><?php esc_html_e( 'Once visitors view pages, you will see them here.', 'opti-behavior' ); ?></div> 280 280 </div> 281 281 <?php else : ?> -
opti-behavior/trunk/includes/trait-opti-behavior-settings-views.php
r3399182 r3408429 696 696 <?php if ($settings_saved): ?> 697 697 <div class="notice notice-success is-dismissible" style="margin: 20px 0;"> 698 <p><?php esc_html_e('Language settings saved successfully. The new language will be applied on the next page load.', 'opti-behavior'); ?></p> 699 </div> 698 <p><?php esc_html_e('Language settings saved successfully. Reloading page to apply new language...', 'opti-behavior'); ?></p> 699 </div> 700 <script> 701 // Auto-reload page after 1 second to apply new language 702 setTimeout(function() { 703 window.location.reload(); 704 }, 1000); 705 </script> 700 706 <?php endif; ?> 701 707 -
opti-behavior/trunk/languages/opti-behavior-fr_FR.po
r3399182 r3408429 1 1 msgid "" 2 2 msgstr "" 3 "Project-Id-Version: Opti-Behavior 1.0. 0\n"3 "Project-Id-Version: Opti-Behavior 1.0.6\n" 4 4 "Report-Msgid-Bugs-To: \n" 5 "POT-Creation-Date: 2025-11- 1119:27+0100\n"6 "PO-Revision-Date: 2025-11- 11 13:13:14+0000\n"5 "POT-Creation-Date: 2025-11-30 19:27+0100\n" 6 "PO-Revision-Date: 2025-11-30 20:00:00+0000\n" 7 7 "Last-Translator: Opti-Behavior Team\n" 8 8 "Language-Team: French\n" … … 178 178 #: includes/trait-opti-behavior-settings-views.php:1663 179 179 msgid "Insufficient permissions" 180 msgstr "Permissions insuffisantes"180 msgstr "Permissions Insuffisantes" 181 181 182 182 #: admin/class-opti-behavior-heatmap-ajax-handler.php:1339 … … 214 214 #: admin/class-opti-behavior-heatmap-dashboard.php:238 215 215 msgid "Dashboard" 216 msgstr "Tableau de bord"216 msgstr "Tableau de Bord" 217 217 218 218 #: admin/class-opti-behavior-heatmap-dashboard.php:159 … … 220 220 #: includes/trait-opti-behavior-heatmaps-views.php:35 221 221 msgid "Heatmaps" 222 msgstr "Cartes de chaleur"222 msgstr "Cartes Chaleur" 223 223 224 224 #: admin/class-opti-behavior-heatmap-dashboard.php:169 … … 228 228 #: includes/trait-opti-behavior-settings-views.php:158 229 229 msgid "Session Recordings" 230 msgstr "Enregistrements de session"230 msgstr "Enregistrements Session" 231 231 232 232 #: admin/class-opti-behavior-heatmap-dashboard.php:170 … … 257 257 #: includes/trait-opti-behavior-dashboard-views.php:99 258 258 msgid "Page Views" 259 msgstr "Pages vues"259 msgstr "Pages Vues" 260 260 261 261 #: admin/class-opti-behavior-heatmap-dashboard.php:242 262 262 #: includes/trait-opti-behavior-dashboard-views.php:126 263 263 msgid "Bounce Rate" 264 msgstr "Taux de rebond"264 msgstr "Taux de Rebond" 265 265 266 266 #: admin/class-opti-behavior-heatmap-dashboard.php:243 267 267 #: includes/trait-opti-behavior-dashboard-views.php:108 268 268 msgid "Avg. Session Time" 269 msgstr " Temps de session moyen"269 msgstr "Durée Moy. Session" 270 270 271 271 #: admin/class-opti-behavior-heatmap-dashboard.php:244 272 272 #: includes/trait-opti-behavior-dashboard-views.php:264 273 273 msgid "Top Pages" 274 msgstr "Pages principales"274 msgstr "Pages Principales" 275 275 276 276 #: admin/class-opti-behavior-heatmap-dashboard.php:245 … … 287 287 #: includes/trait-opti-behavior-dashboard-views.php:170 288 288 msgid "Real-time Visitors" 289 msgstr "Visiteurs en temps réel"289 msgstr "Visiteurs en Temps Réel" 290 290 291 291 #: admin/class-opti-behavior-heatmap-dashboard.php:249 … … 338 338 #: includes/trait-opti-behavior-dashboard-views.php:48 339 339 msgid "Last 7 Days" 340 msgstr " Les 7 derniers jours"340 msgstr "7 Derniers Jours" 341 341 342 342 #: admin/class-opti-behavior-heatmap-dashboard.php:258 … … 345 345 #: includes/trait-opti-behavior-dashboard-views.php:49 346 346 msgid "Last 30 Days" 347 msgstr " Les 30 derniers jours"347 msgstr "30 Derniers Jours" 348 348 349 349 #: admin/class-opti-behavior-heatmap-dashboard.php:259 350 350 #: includes/trait-opti-behavior-dashboard-views.php:50 351 351 msgid "This Month" 352 msgstr "Ce mois-ci"352 msgstr "Ce Mois" 353 353 354 354 #: admin/class-opti-behavior-heatmap-dashboard.php:260 355 355 msgid "Last Month" 356 msgstr " Le mois dernier"356 msgstr "Mois Dernier" 357 357 358 358 #: admin/class-opti-behavior-heatmap-dashboard.php:261 … … 366 366 #: includes/trait-opti-behavior-dashboard-views.php:1139 367 367 msgid "No data available" 368 msgstr "Aucune donnée disponible"368 msgstr "Aucune Donnée" 369 369 370 370 #: admin/class-opti-behavior-heatmap-dashboard.php:263 … … 376 376 #: views/dashboard-views.php:233 377 377 msgid "Top Engaged Users" 378 msgstr "Utilisateurs les plus engagés"378 msgstr "Utilisateurs les Plus Engagés" 379 379 380 380 #: admin/class-opti-behavior-heatmap-dashboard.php:390 … … 435 435 #: includes/trait-opti-behavior-dashboard-views.php:169 436 436 msgid "Live" 437 msgstr "En direct"437 msgstr "En Direct" 438 438 439 439 #: admin/class-opti-behavior-heatmap-dashboard.php:449 440 440 #: includes/trait-opti-behavior-dashboard-views.php:188 441 441 msgid "No active visitors right now" 442 msgstr "Aucun visiteur actif pour le moment"442 msgstr "Aucun Visiteur Actif" 443 443 444 444 #: admin/class-opti-behavior-heatmap-dashboard.php:450 445 445 #: includes/trait-opti-behavior-dashboard-views.php:189 446 446 msgid "Traffic updates in real-time." 447 msgstr "Le trafic se met à jour en temps réel."447 msgstr "Le Trafic se Met à Jour en Temps Réel." 448 448 449 449 #: admin/class-opti-behavior-heatmap-dashboard.php:463 … … 518 518 #: includes/trait-opti-behavior-sessions-views.php:190 519 519 msgid "View Details" 520 msgstr "Voir les détails"520 msgstr "Voir Détails" 521 521 522 522 #: admin/class-opti-behavior-heatmap-dashboard.php:635 … … 546 546 #: admin/class-opti-behavior-heatmap-dashboard.php:714 547 547 msgid "Loading analytics data..." 548 msgstr "Chargement des données d'analyse..."548 msgstr "Chargement des Données..." 549 549 550 550 #: admin/class-opti-behavior-heatmap-dashboard.php:775 … … 596 596 #: admin/class-opti-behavior-heatmap-dashboard.php:815 597 597 msgid "First" 598 msgstr "Premi ère"598 msgstr "Premier" 599 599 600 600 #: admin/class-opti-behavior-heatmap-dashboard.php:816 601 601 msgid "Prev" 602 msgstr "Préc "602 msgstr "Précédent" 603 603 604 604 #: admin/class-opti-behavior-heatmap-dashboard.php:830 605 605 msgid "Next" 606 msgstr "Suiv "606 msgstr "Suivant" 607 607 608 608 #: admin/class-opti-behavior-heatmap-dashboard.php:831 609 609 msgid "Last" 610 msgstr "Derni ère"610 msgstr "Dernier" 611 611 612 612 #: admin/class-opti-behavior-heatmap-dashboard.php:2025 … … 712 712 #: admin/class-opti-behavior-heatmap-post-metabox.php:208 713 713 msgid "Exit Behavior" 714 msgstr "Comportement de sortie"714 msgstr "Comportement de Sortie" 715 715 716 716 #: admin/class-opti-behavior-heatmap-post-metabox.php:209 … … 764 764 #: admin/recordings-page.php:32 765 765 msgid "Date Range:" 766 msgstr "P lage de dates:"766 msgstr "Période :" 767 767 768 768 #: admin/recordings-page.php:38 769 769 #: includes/trait-opti-behavior-dashboard-views.php:51 770 770 msgid "Custom Range" 771 msgstr "P lage personnalisée"771 msgstr "Période Personnalisée" 772 772 773 773 #: admin/recordings-page.php:41 … … 777 777 #: admin/recordings-page.php:43 778 778 msgid "All Durations" 779 msgstr "Toutes les durées"779 msgstr "Toutes Durées" 780 780 781 781 #: admin/recordings-page.php:44 … … 818 818 #: admin/recordings-page.php:64 819 819 msgid "Advanced Filters" 820 msgstr "Filtres avancés"820 msgstr "Filtres Avancés" 821 821 822 822 #: admin/recordings-page.php:69 823 823 msgid "Clear All" 824 msgstr " Tout effacer"824 msgstr "Effacer Tout" 825 825 826 826 #: admin/recordings-page.php:76 … … 839 839 #: admin/recordings-page.php:93 840 840 msgid "Visitor Attributes" 841 msgstr "Attributs du visiteur"841 msgstr "Attributs Visiteur" 842 842 843 843 #: admin/recordings-page.php:96 844 844 msgid "Browser Name" 845 msgstr "N om du navigateur"845 msgstr "Navigateur" 846 846 847 847 #: admin/recordings-page.php:98 848 848 msgid "All Browsers" 849 msgstr "Tous les navigateurs"849 msgstr "Tous Navigateurs" 850 850 851 851 #: admin/recordings-page.php:105 852 852 msgid "All Countries" 853 msgstr "Tous les pays"853 msgstr "Tous Pays" 854 854 855 855 #: admin/recordings-page.php:110 856 856 msgid "Device Type" 857 msgstr "Type d' appareil"857 msgstr "Type d'Appareil" 858 858 859 859 #: admin/recordings-page.php:112 860 860 msgid "All Devices" 861 msgstr "Tous les appareils"861 msgstr "Tous Appareils" 862 862 863 863 #: admin/recordings-page.php:113 … … 873 873 #: admin/recordings-page.php:120 admin/recordings-page.php:364 874 874 msgid "Operating System" 875 msgstr "Système d' exploitation"875 msgstr "Système d'Exploitation" 876 876 877 877 #: admin/recordings-page.php:122 878 878 msgid "All OS" 879 msgstr "Tous les OS"879 msgstr "Tous SE" 880 880 881 881 #: admin/recordings-page.php:127 882 882 msgid "Visitor Type" 883 msgstr "Type de visiteur"883 msgstr "Type Visiteur" 884 884 885 885 #: admin/recordings-page.php:129 886 886 msgid "All Visitors" 887 msgstr "Tous les visiteurs"887 msgstr "Tous Visiteurs" 888 888 889 889 #: admin/recordings-page.php:130 890 890 msgid "New Visitor" 891 msgstr "Nouveau visiteur"891 msgstr "Nouveau Visiteur" 892 892 893 893 #: admin/recordings-page.php:131 894 894 msgid "Returning Visitor" 895 msgstr "Visiteur récurrent"895 msgstr "Visiteur Récurrent" 896 896 897 897 #: admin/recordings-page.php:138 898 898 msgid "Session Attributes" 899 msgstr "Attributs de session"899 msgstr "Attributs Session" 900 900 901 901 #: admin/recordings-page.php:141 902 902 msgid "Recording ID" 903 msgstr "ID d'enregistrement"903 msgstr "ID Enregistrement" 904 904 905 905 #: admin/recordings-page.php:142 906 906 msgid "Enter recording ID" 907 msgstr "Entre r l'ID d'enregistrement"907 msgstr "Entrez ID" 908 908 909 909 #: admin/recordings-page.php:146 910 910 msgid "Min Duration (seconds)" 911 msgstr "Durée minimale (secondes)"911 msgstr "Durée Minimale (secondes)" 912 912 913 913 #: admin/recordings-page.php:151 914 914 msgid "Max Duration (seconds)" 915 msgstr "Durée maximale (secondes)"915 msgstr "Durée Max (s)" 916 916 917 917 #: admin/recordings-page.php:156 918 918 msgid "Min Page Count" 919 msgstr " Nombre minimum de pages"919 msgstr "Pages Min" 920 920 921 921 #: admin/recordings-page.php:161 922 922 msgid "Max Page Count" 923 msgstr " Nombre maximum de pages"923 msgstr "Pages Max" 924 924 925 925 #: admin/recordings-page.php:166 926 926 msgid "Watched Status" 927 msgstr "Statut de visionnage"927 msgstr "Statut Vue" 928 928 929 929 #: admin/recordings-page.php:168 930 930 msgid "All Recordings" 931 msgstr "Tous les enregistrements"931 msgstr "Tous Enregistrements" 932 932 933 933 #: admin/recordings-page.php:169 934 934 msgid "Watched" 935 msgstr " Regardé"935 msgstr "Vu" 936 936 937 937 #: admin/recordings-page.php:170 938 938 msgid "Not Watched" 939 msgstr "Non regardé"939 msgstr "Non Vu" 940 940 941 941 #: admin/recordings-page.php:177 942 942 msgid "Pages & Traffic" 943 msgstr "Pages et trafic"943 msgstr "Pages & Trafic" 944 944 945 945 #: admin/recordings-page.php:180 946 946 msgid "Contains Page" 947 msgstr "Contient la page"947 msgstr "Contient Page" 948 948 949 949 #: admin/recordings-page.php:181 950 950 msgid "e.g., /product" 951 msgstr "ex. ,/produit"951 msgstr "ex. /produit" 952 952 953 953 #: admin/recordings-page.php:185 954 954 msgid "Does Not Contain Page" 955 msgstr " Ne contient pas la page"955 msgstr "Exclut Page" 956 956 957 957 #: admin/recordings-page.php:186 958 958 msgid "e.g., /checkout" 959 msgstr "ex. , /checkout"959 msgstr "ex. /paiement" 960 960 961 961 #: admin/recordings-page.php:190 962 962 msgid "Entry Page" 963 msgstr "Page d'entrée"963 msgstr "Page Entrée" 964 964 965 965 #: admin/recordings-page.php:191 966 966 msgid "e.g., /home" 967 msgstr "ex. , /home"967 msgstr "ex. /accueil" 968 968 969 969 #: admin/recordings-page.php:195 970 970 msgid "Exit Page" 971 msgstr "Page de sortie"971 msgstr "Page Sortie" 972 972 973 973 #: admin/recordings-page.php:196 974 974 msgid "e.g., /thank-you" 975 msgstr "ex. ,/merci"975 msgstr "ex. /merci" 976 976 977 977 #: admin/recordings-page.php:200 978 978 msgid "Referrer URL" 979 msgstr "URL du référent"979 msgstr "URL Référent" 980 980 981 981 #: admin/recordings-page.php:201 982 982 msgid "e.g., google.com" 983 msgstr "ex. , google.com"983 msgstr "ex. google.fr" 984 984 985 985 #: admin/recordings-page.php:205 986 986 msgid "Traffic Channel" 987 msgstr "Canal de trafic"987 msgstr "Canal Trafic" 988 988 989 989 #: admin/recordings-page.php:207 990 990 msgid "All Channels" 991 msgstr "Tous les canaux"991 msgstr "Tous Canaux" 992 992 993 993 #: admin/recordings-page.php:208 994 994 msgid "Direct Visit" 995 msgstr "Visite directe"995 msgstr "Visite Directe" 996 996 997 997 #: admin/recordings-page.php:209 998 998 msgid "Organic Search" 999 msgstr "Recherche organique"999 msgstr "Recherche Organique" 1000 1000 1001 1001 #: admin/recordings-page.php:210 1002 1002 msgid "Paid Ads" 1003 msgstr "Pub licités payantes"1003 msgstr "Pubs Payantes" 1004 1004 1005 1005 #: admin/recordings-page.php:211 1006 1006 msgid "Social Media" 1007 msgstr " Médias sociaux"1007 msgstr "Réseaux Sociaux" 1008 1008 1009 1009 #: admin/recordings-page.php:212 … … 1025 1025 #: admin/recordings-page.php:225 1026 1026 msgid "All Campaigns" 1027 msgstr "Toutes les campagnes"1027 msgstr "Toutes Campagnes" 1028 1028 1029 1029 #: admin/recordings-page.php:230 … … 1033 1033 #: admin/recordings-page.php:232 1034 1034 msgid "All Sources" 1035 msgstr "Toutes les sources"1035 msgstr "Toutes Sources" 1036 1036 1037 1037 #: admin/recordings-page.php:237 1038 1038 msgid "UTM Medium" 1039 msgstr "M édium UTM"1039 msgstr "Medium UTM" 1040 1040 1041 1041 #: admin/recordings-page.php:239 1042 1042 msgid "All Mediums" 1043 msgstr "Tous les médiums"1043 msgstr "Tous Mediums" 1044 1044 1045 1045 #: admin/recordings-page.php:248 1046 1046 msgid "Apply Filters" 1047 msgstr "Appliquer les filtres"1047 msgstr "Appliquer Filtres" 1048 1048 1049 1049 #: admin/recordings-page.php:252 … … 1053 1053 #: admin/recordings-page.php:261 1054 1054 msgid "List View" 1055 msgstr "Vue liste"1055 msgstr "Vue Liste" 1056 1056 1057 1057 #: admin/recordings-page.php:265 1058 1058 msgid "Table View (By Page)" 1059 msgstr "Vue tableau (par page)"1059 msgstr "Vue Tableau" 1060 1060 1061 1061 #: admin/recordings-page.php:274 admin/recordings-page.php:299 1062 1062 msgid "Loading recordings..." 1063 msgstr "Chargement des enregistrements..."1063 msgstr "Chargement..." 1064 1064 1065 1065 #: admin/recordings-page.php:289 1066 1066 msgid "Total Duration" 1067 msgstr "Durée totale"1067 msgstr "Durée Totale" 1068 1068 1069 1069 #: admin/recordings-page.php:290 1070 1070 msgid "Avg Duration" 1071 msgstr "Durée moyenne"1071 msgstr "Durée Moy." 1072 1072 1073 1073 #: admin/recordings-page.php:291 1074 1074 msgid "Last Recorded" 1075 msgstr "Dernier enregistrement"1075 msgstr "Dernier Enreg." 1076 1076 1077 1077 #: admin/recordings-page.php:321 … … 1086 1086 #: includes/trait-opti-behavior-dashboard-views.php:396 1087 1087 msgid "Screen Resolution" 1088 msgstr "Résolution d'écran"1088 msgstr "Résolution Écran" 1089 1089 1090 1090 #: admin/recordings-page.php:387 1091 1091 msgid "Loading recording..." 1092 msgstr "Chargement de l'enregistrement..."1092 msgstr "Chargement..." 1093 1093 1094 1094 #: admin/recordings-page.php:420 … … 1098 1098 #: admin/recordings-page.php:431 1099 1099 msgid "Skip Inactive" 1100 msgstr "Ignorer les inactifs"1100 msgstr "Ignorer Inactivité" 1101 1101 1102 1102 #: admin/recordings-page.php:439 1103 1103 msgid "Session Timeline" 1104 msgstr "Chronologie de session"1104 msgstr "Chronologie" 1105 1105 1106 1106 #: admin/recordings-page.php:445 1107 1107 msgid "Loading timeline..." 1108 msgstr "Chargement de la chronologie..."1108 msgstr "Chargement..." 1109 1109 1110 1110 #: clear-cache.php:14 … … 1134 1134 #: includes/trait-opti-behavior-ai-insights-views.php:58 1135 1135 msgid "Coming Soon" 1136 msgstr " "1136 msgstr "Bientôt Disponible" 1137 1137 1138 1138 #: includes/trait-opti-behavior-ai-insights-views.php:96 … … 1160 1160 #: includes/trait-opti-behavior-ai-insights-views.php:112 1161 1161 msgid "Issue Detection" 1162 msgstr "Détection de bot"1162 msgstr "Détection de Bot" 1163 1163 1164 1164 #: includes/trait-opti-behavior-ai-insights-views.php:113 … … 1180 1180 #: includes/trait-opti-behavior-ai-insights-views.php:124 1181 1181 msgid "Performance Optimization" 1182 msgstr " "1182 msgstr "Optimisation des Performances" 1183 1183 1184 1184 #: includes/trait-opti-behavior-ai-insights-views.php:125 … … 1210 1210 #: includes/trait-opti-behavior-ai-insights-views.php:143 1211 1211 msgid "What Our AI Will Analyze" 1212 msgstr " "1212 msgstr "Ce que Notre IA Analysera" 1213 1213 1214 1214 #: includes/trait-opti-behavior-ai-insights-views.php:147 1215 1215 msgid "Traffic Patterns" 1216 msgstr " Enregistrer les paramètres de trafic"1216 msgstr "Modèles de Trafic" 1217 1217 1218 1218 #: includes/trait-opti-behavior-ai-insights-views.php:151 1219 1219 msgid "Sales Funnels" 1220 msgstr " "1220 msgstr "Tunnels de Vente" 1221 1221 1222 1222 #: includes/trait-opti-behavior-ai-insights-views.php:155 1223 1223 msgid "Engagement Time" 1224 msgstr " "1224 msgstr "Temps d'Engagement" 1225 1225 1226 1226 #: includes/trait-opti-behavior-ai-insights-views.php:159 1227 1227 msgid "Click Behavior" 1228 msgstr "Comportement de sortie"1228 msgstr "Comportement de Sortie" 1229 1229 1230 1230 #: includes/trait-opti-behavior-ai-insights-views.php:163 1231 1231 msgid "Device Performance" 1232 msgstr " "1232 msgstr "Performance par Appareil" 1233 1233 1234 1234 #: includes/trait-opti-behavior-ai-insights-views.php:167 1235 1235 msgid "Geographic Trends" 1236 msgstr " "1236 msgstr "Tendances Géographiques" 1237 1237 1238 1238 #: includes/trait-opti-behavior-ai-insights-views.php:171 1239 1239 msgid "User Journeys" 1240 msgstr " "1240 msgstr "Parcours Utilisateurs" 1241 1241 1242 1242 #: includes/trait-opti-behavior-ai-insights-views.php:175 1243 1243 msgid "Revenue Impact" 1244 msgstr " "1244 msgstr "Impact sur les Revenus" 1245 1245 1246 1246 #: includes/trait-opti-behavior-ai-insights-views.php:184 … … 1268 1268 #: includes/trait-opti-behavior-ai-insights-views.php:212 1269 1269 msgid "Development Roadmap" 1270 msgstr " "1270 msgstr "Plan de Développement" 1271 1271 1272 1272 #: includes/trait-opti-behavior-ai-insights-views.php:217 1273 1273 msgid "Phase 1: Foundation" 1274 msgstr " "1274 msgstr "Phase 1 : Fondation" 1275 1275 1276 1276 #: includes/trait-opti-behavior-ai-insights-views.php:218 1277 1277 msgid "Advanced analytics data collection and processing infrastructure" 1278 msgstr " "1278 msgstr "Infrastructure de Collecte et de Traitement de Données" 1279 1279 1280 1280 #: includes/trait-opti-behavior-ai-insights-views.php:224 1281 1281 msgid "Phase 2: AI Integration" 1282 msgstr " "1282 msgstr "Phase 2 : Intégration de l'IA" 1283 1283 1284 1284 #: includes/trait-opti-behavior-ai-insights-views.php:225 1285 1285 msgid "Machine learning models for pattern recognition and insights" 1286 msgstr " "1286 msgstr "Modèles d'Apprentissage pour Reconnaissance de Modèles" 1287 1287 1288 1288 #: includes/trait-opti-behavior-ai-insights-views.php:231 … … 1296 1296 #: includes/trait-opti-behavior-ai-insights-views.php:238 1297 1297 msgid "Phase 4: Launch" 1298 msgstr " "1298 msgstr "Phase 4 : Lancement" 1299 1299 1300 1300 #: includes/trait-opti-behavior-ai-insights-views.php:239 1301 1301 msgid "Full AI-powered analytics suite with predictive capabilities" 1302 msgstr " "1302 msgstr "Suite Complète d'Analyses IA avec Capacités Prédictives" 1303 1303 1304 1304 #: includes/trait-opti-behavior-ajax-handlers.php:88 … … 1374 1374 #: includes/trait-opti-behavior-dashboard-views.php:39 1375 1375 msgid "Analytics Dashboard" 1376 msgstr "Tableau de bord analytique"1376 msgstr "Tableau de Bord Analytique" 1377 1377 1378 1378 #: includes/trait-opti-behavior-dashboard-views.php:41 1379 1379 msgid "Real-time insights and user behavior analytics" 1380 msgstr " "1380 msgstr "Analyses en Temps Réel" 1381 1381 "Informations en temps réel et analyses du comportement des utilisateurs" 1382 1382 … … 1387 1387 #: includes/trait-opti-behavior-dashboard-views.php:117 1388 1388 msgid "Avg. Scroll Depth" 1389 msgstr " Profondeur de défilement moy."1389 msgstr "Défilement Moy." 1390 1390 1391 1391 #: includes/trait-opti-behavior-dashboard-views.php:199 1392 1392 msgid "Real-time Visitor Map" 1393 msgstr "Carte des visiteurs en temps réel"1393 msgstr "Carte des Visiteurs en Temps Réel" 1394 1394 1395 1395 #: includes/trait-opti-behavior-dashboard-views.php:214 1396 1396 msgid "Traffic Overview" 1397 msgstr "Aperçu du trafic"1397 msgstr "Aperçu du Trafic" 1398 1398 1399 1399 #: includes/trait-opti-behavior-dashboard-views.php:273 1400 1400 msgid "Once visitors view pages, you'll see them here." 1401 msgstr " Une fois que les visiteurs consultent des pages, vous les verrez ici."1401 msgstr "Les Pages Vues Apparaîtront Ici." 1402 1402 1403 1403 #: includes/trait-opti-behavior-dashboard-views.php:299 1404 1404 msgid "Visitor Activity Heatmap" 1405 msgstr "Carte de chaleur de l'activité des visiteurs"1405 msgstr "Carte Activité Visiteurs" 1406 1406 1407 1407 #: includes/trait-opti-behavior-dashboard-views.php:306 … … 1411 1411 #: includes/trait-opti-behavior-dashboard-views.php:332 1412 1412 msgid "User Intent" 1413 msgstr "Intention de l' utilisateur"1413 msgstr "Intention de l'Utilisateur" 1414 1414 1415 1415 #: includes/trait-opti-behavior-dashboard-views.php:344 1416 1416 msgid "Top Referrers" 1417 msgstr "Principaux référents"1417 msgstr "Principaux Référents" 1418 1418 1419 1419 #: includes/trait-opti-behavior-dashboard-views.php:354 1420 1420 msgid "Top Countries" 1421 msgstr "Principaux pays"1421 msgstr "Principaux Pays" 1422 1422 1423 1423 #: includes/trait-opti-behavior-dashboard-views.php:376 1424 1424 msgid "Device Types" 1425 msgstr "Types d' appareils"1425 msgstr "Types d'Appareils" 1426 1426 1427 1427 #: includes/trait-opti-behavior-dashboard-views.php:386 1428 1428 msgid "Operating Systems" 1429 msgstr "Systèmes d' exploitation"1429 msgstr "Systèmes d'Exploitation" 1430 1430 1431 1431 #: includes/trait-opti-behavior-dashboard-views.php:448 … … 1434 1434 #: includes/trait-opti-behavior-dashboard-views.php:1140 1435 1435 msgid "Try broadening the date range or check back later." 1436 msgstr " Essayez d'élargir la plage de dates ou revenez plus tard."1436 msgstr "Élargir la Période ou Revenir Plus Tard." 1437 1437 1438 1438 #: includes/trait-opti-behavior-dashboard-views.php:459 1439 1439 msgid "Low intent" 1440 msgstr "Faible intention"1440 msgstr "Faible Intention" 1441 1441 1442 1442 #: includes/trait-opti-behavior-dashboard-views.php:461 … … 1456 1456 #: includes/trait-opti-behavior-dashboard-views.php:465 1457 1457 msgid "Medium intent" 1458 msgstr "Intention moyenne"1458 msgstr "Intention Moyenne" 1459 1459 1460 1460 #: includes/trait-opti-behavior-dashboard-views.php:471 1461 1461 msgid "High intent" 1462 msgstr "Forte intention"1462 msgstr "Forte Intention" 1463 1463 1464 1464 #: includes/trait-opti-behavior-dashboard-views.php:780 … … 1466 1466 #: includes/trait-opti-behavior-settings-views.php:1747 1467 1467 msgid "Traffic Classification" 1468 msgstr "Classification du trafic"1468 msgstr "Classification du Trafic" 1469 1469 1470 1470 #: includes/trait-opti-behavior-dashboard-views.php:824 … … 1492 1492 #: includes/trait-opti-behavior-dashboard-views.php:944 1493 1493 msgid "Bot Traffic" 1494 msgstr "Trafic de bots"1494 msgstr "Trafic de Bots" 1495 1495 1496 1496 #: includes/trait-opti-behavior-dashboard-views.php:927 1497 1497 msgid "No bot visits detected" 1498 msgstr "Aucune visite de bot détectée"1498 msgstr "Aucune Visite de Bot Détectée" 1499 1499 1500 1500 #: includes/trait-opti-behavior-dashboard-views.php:928 1501 1501 msgid "Bot visits will appear here when detected." 1502 msgstr "Les visites de bots apparaîtront ici lorsqu'elles seront détectées."1502 msgstr "Les Visites de Bots Apparaîtront Ici." 1503 1503 1504 1504 #: includes/trait-opti-behavior-heatmaps-views.php:37 … … 1508 1508 #: includes/trait-opti-behavior-heatmaps-views.php:58 1509 1509 msgid "Total Heatmaps" 1510 msgstr " Cartes de chaleur"1510 msgstr "Total des Cartes de Chaleur" 1511 1511 1512 1512 #: includes/trait-opti-behavior-heatmaps-views.php:59 1513 1513 msgid "this week" 1514 msgstr "cette semaine"1514 msgstr "cette Semaine" 1515 1515 1516 1516 #: includes/trait-opti-behavior-heatmaps-views.php:67 1517 1517 msgid "Total Clicks" 1518 msgstr "Total des clics"1518 msgstr "Total des Clics" 1519 1519 1520 1520 #: includes/trait-opti-behavior-heatmaps-views.php:68 … … 1524 1524 #: includes/trait-opti-behavior-heatmaps-views.php:76 1525 1525 msgid "Mobile Traffic" 1526 msgstr "Trafic mobile"1526 msgstr "Trafic Mobile" 1527 1527 1528 1528 #: includes/trait-opti-behavior-heatmaps-views.php:77 … … 1532 1532 #: includes/trait-opti-behavior-heatmaps-views.php:85 1533 1533 msgid "Avg. Time on Page" 1534 msgstr "Temps moyen sur la page"1534 msgstr "Temps Moy. Page" 1535 1535 1536 1536 #: includes/trait-opti-behavior-heatmaps-views.php:86 … … 1540 1540 #: includes/trait-opti-behavior-heatmaps-views.php:94 1541 1541 msgid "Hottest Page" 1542 msgstr " Dernière page"1542 msgstr "Page la Plus Chaude" 1543 1543 1544 1544 #: includes/trait-opti-behavior-heatmaps-views.php:103 1545 1545 msgid "Click-through Rate" 1546 msgstr "Taux de clics"1546 msgstr "Taux de Clics" 1547 1547 1548 1548 #: includes/trait-opti-behavior-heatmaps-views.php:104 … … 1552 1552 #: includes/trait-opti-behavior-heatmaps-views.php:124 1553 1553 msgid "Available Heatmaps" 1554 msgstr " Visualisation des cartes de chaleur"1554 msgstr "Cartes de Chaleur Disponibles" 1555 1555 1556 1556 #: includes/trait-opti-behavior-maintenance.php:88 … … 1572 1572 #: includes/trait-opti-behavior-sessions-views.php:49 1573 1573 msgid "Active" 1574 msgstr "Acti ons"1574 msgstr "Actif" 1575 1575 1576 1576 #: includes/trait-opti-behavior-sessions-views.php:57 … … 1588 1588 #: includes/trait-opti-behavior-sessions-views.php:83 1589 1589 msgid "Select All" 1590 msgstr "Tout effacer"1590 msgstr "Tout Sélectionner" 1591 1591 1592 1592 #: includes/trait-opti-behavior-sessions-views.php:84 … … 1625 1625 #: includes/trait-opti-behavior-settings-views.php:1736 1626 1626 msgid "Dashboard Settings" 1627 msgstr "Paramètres du tableau de bord"1627 msgstr "Paramètres du Tableau de Bord" 1628 1628 1629 1629 #: includes/trait-opti-behavior-settings-views.php:153 1630 1630 #: includes/trait-opti-behavior-settings-views.php:246 1631 1631 msgid "Heatmap Settings" 1632 msgstr "Paramètres de carte de chaleur"1632 msgstr "Paramètres de Carte de Chaleur" 1633 1633 1634 1634 #: includes/trait-opti-behavior-settings-views.php:163 1635 1635 msgid "License & Quota" 1636 msgstr "Licence et quota"1636 msgstr "Licence et Quota" 1637 1637 1638 1638 #: includes/trait-opti-behavior-settings-views.php:168 1639 1639 msgid "Data Protection" 1640 msgstr "Protection des données"1640 msgstr "Protection des Données" 1641 1641 1642 1642 #: includes/trait-opti-behavior-settings-views.php:173 … … 1646 1646 #: includes/trait-opti-behavior-settings-views.php:178 1647 1647 msgid "Debug & Logging" 1648 msgstr "Débogage et journalisation"1648 msgstr "Débogage et Journalisation" 1649 1649 1650 1650 #: includes/trait-opti-behavior-settings-views.php:183 1651 1651 msgid "Danger Zone" 1652 msgstr "Zone dangereuse"1652 msgstr "Zone Dangereuse" 1653 1653 1654 1654 #: includes/trait-opti-behavior-settings-views.php:188 1655 1655 #: includes/trait-opti-behavior-settings-views.php:588 1656 1656 msgid "Uninstall Settings" 1657 msgstr "Paramètres de désinstallation"1657 msgstr "Paramètres de Désinstallation" 1658 1658 1659 1659 #: includes/trait-opti-behavior-settings-views.php:248 … … 2380 2380 #: includes/trait-opti-behavior-settings-views.php:1379 2381 2381 msgid "days" 2382 msgstr " "2382 msgstr "jours" 2383 2383 2384 2384 #: includes/trait-opti-behavior-settings-views.php:1386 … … 2480 2480 #: includes/trait-opti-behavior-settings-views.php:2126 2481 2481 msgid "Save Recording Settings" 2482 msgstr "Enregistrer les paramètres d'enregistrement"2482 msgstr "Enregistrer Paramètres" 2483 2483 2484 2484 #: includes/trait-opti-behavior-settings-views.php:1544 … … 2537 2537 #: includes/trait-opti-behavior-settings-views.php:2267 2538 2538 msgid "Upgrade to Pro" 2539 msgstr " Mettre à niveau versPro"2539 msgstr "Passer à Pro" 2540 2540 2541 2541 #: includes/trait-opti-behavior-settings-views.php:1574 … … 2561 2561 #: includes/trait-opti-behavior-settings-views.php:1756 2562 2562 msgid "User Intent Rules" 2563 msgstr "Règles d' intention utilisateur"2563 msgstr "Règles d'Intention Utilisateur" 2564 2564 2565 2565 #: includes/trait-opti-behavior-settings-views.php:1789 … … 2570 2570 #: includes/trait-opti-behavior-settings-views.php:1793 2571 2571 msgid "Bot Detection" 2572 msgstr "Détection de bot"2572 msgstr "Détection de Bot" 2573 2573 2574 2574 #: includes/trait-opti-behavior-settings-views.php:1797 2575 2575 msgid "Enable bot traffic detection" 2576 msgstr "Activer la détection de trafic de bot"2576 msgstr "Activer Détection Trafic Bot" 2577 2577 2578 2578 #: includes/trait-opti-behavior-settings-views.php:1799 … … 2586 2586 #: includes/trait-opti-behavior-settings-views.php:1804 2587 2587 msgid "Automated Traffic Detection" 2588 msgstr "Détection de trafic automatisé"2588 msgstr "Détection de Trafic Automatisé" 2589 2589 2590 2590 #: includes/trait-opti-behavior-settings-views.php:1808 2591 2591 msgid "Enable automated traffic detection" 2592 msgstr "Activer la détection de trafic automatisé"2592 msgstr "Activer Détection Trafic Automatisé" 2593 2593 2594 2594 #: includes/trait-opti-behavior-settings-views.php:1810 … … 2602 2602 #: includes/trait-opti-behavior-settings-views.php:1815 2603 2603 msgid "Spam Traffic Detection" 2604 msgstr "Détection de trafic spam"2604 msgstr "Détection de Trafic Spam" 2605 2605 2606 2606 #: includes/trait-opti-behavior-settings-views.php:1819 2607 2607 msgid "Enable spam traffic detection" 2608 msgstr "Activer la détection de trafic spam"2608 msgstr "Activer Détection Trafic Spam" 2609 2609 2610 2610 #: includes/trait-opti-behavior-settings-views.php:1821 … … 2616 2616 #: includes/trait-opti-behavior-settings-views.php:1826 2617 2617 msgid "Spam Duration Threshold" 2618 msgstr "Seuil de durée de spam"2618 msgstr "Seuil de Durée de Spam" 2619 2619 2620 2620 #: includes/trait-opti-behavior-settings-views.php:1830 … … 2625 2625 #: includes/trait-opti-behavior-settings-views.php:1835 2626 2626 msgid "Spam Bounce Threshold" 2627 msgstr "Seuil de rebond de spam"2627 msgstr "Seuil de Rebond de Spam" 2628 2628 2629 2629 #: includes/trait-opti-behavior-settings-views.php:1839 … … 2634 2634 #: includes/trait-opti-behavior-settings-views.php:1844 2635 2635 msgid "Custom Bot Patterns" 2636 msgstr "Modèles de bot personnalisés"2636 msgstr "Modèles de Bot Personnalisés" 2637 2637 2638 2638 #: includes/trait-opti-behavior-settings-views.php:1847 … … 2646 2646 #: includes/trait-opti-behavior-settings-views.php:1852 2647 2647 msgid "Save Traffic Settings" 2648 msgstr "Enregistrer les paramètres de trafic"2648 msgstr "Enregistrer Paramètres Trafic" 2649 2649 2650 2650 #: includes/trait-opti-behavior-settings-views.php:1886 … … 2655 2655 #: includes/trait-opti-behavior-settings-views.php:1892 2656 2656 msgid "Low Intent" 2657 msgstr " "2657 msgstr "Faible Intention" 2658 2658 2659 2659 #: includes/trait-opti-behavior-settings-views.php:1896 … … 2681 2681 #: includes/trait-opti-behavior-settings-views.php:1988 2682 2682 msgid "Scroll Depth (%)" 2683 msgstr " "2683 msgstr "Profondeur de Défilement (%)" 2684 2684 2685 2685 #: includes/trait-opti-behavior-settings-views.php:1919 … … 2689 2689 #: includes/trait-opti-behavior-settings-views.php:1929 2690 2690 msgid "Medium Intent" 2691 msgstr " "2691 msgstr "Intention Moyenne" 2692 2692 2693 2693 #: includes/trait-opti-behavior-settings-views.php:1938 … … 2705 2705 #: includes/trait-opti-behavior-settings-views.php:1966 2706 2706 msgid "High Intent" 2707 msgstr " "2707 msgstr "Forte Intention" 2708 2708 2709 2709 #: includes/trait-opti-behavior-settings-views.php:1975 … … 2721 2721 #: includes/trait-opti-behavior-settings-views.php:1999 2722 2722 msgid "Save User Intent Rules" 2723 msgstr " Règles d'intention utilisateur"2723 msgstr "Enregistrer Règles Intention" 2724 2724 2725 2725 #: includes/trait-opti-behavior-settings-views.php:2027 2726 2726 msgid "Recording settings saved successfully!" 2727 msgstr "Paramètres d'enregistrement enregistrés avec succès !"2727 msgstr "Paramètres enregistrés !" 2728 2728 2729 2729 #: includes/trait-opti-behavior-settings-views.php:2038 2730 2730 msgid "Session Recording Settings" 2731 msgstr "Paramètres d'enregistrement de session"2731 msgstr "Paramètres Enregistrement" 2732 2732 2733 2733 #: includes/trait-opti-behavior-settings-views.php:2040 2734 2734 msgid "Configure how session recordings are captured and stored" 2735 msgstr " "2735 msgstr "Configuration capture et stockage" 2736 2736 "Configurer comment les enregistrements de session sont capturés et stockés" 2737 2737 2738 2738 #: includes/trait-opti-behavior-settings-views.php:2046 2739 2739 msgid "Enable Session Recording" 2740 msgstr "Activer l'enregistrement de session"2740 msgstr "Activer Enregistrement" 2741 2741 2742 2742 #: includes/trait-opti-behavior-settings-views.php:2047 2743 2743 msgid "Record user sessions for playback and analysis" 2744 msgstr "Enregistrer les sessions utilisateur pour la lecture et l'analyse"2744 msgstr "Enregistrer sessions pour analyse" 2745 2745 2746 2746 #: includes/trait-opti-behavior-settings-views.php:2059 2747 2747 msgid "Max Recording Duration" 2748 msgstr "Durée maximale d'enregistrement"2748 msgstr "Durée Max Enregistrement" 2749 2749 2750 2750 #: includes/trait-opti-behavior-settings-views.php:2060 2751 2751 msgid "Maximum duration for each recording session (in seconds)" 2752 msgstr "Durée maximale p our chaque session d'enregistrement (ensecondes)"2752 msgstr "Durée maximale par session (secondes)" 2753 2753 2754 2754 #: includes/trait-opti-behavior-settings-views.php:2072 2755 2755 msgid "Mouse Movement Sample Rate" 2756 msgstr "Taux d'échantillonnage du mouvement de la souris"2756 msgstr "Taux Échantillonnage Souris" 2757 2757 2758 2758 #: includes/trait-opti-behavior-settings-views.php:2073 2759 2759 msgid "How often to capture mouse movements (lower = more data)" 2760 msgstr " "2760 msgstr "Fréquence capture (+ bas = + données)" 2761 2761 "À quelle fréquence capturer les mouvements de souris (plus bas = plus de " 2762 2762 "données)" … … 2764 2764 #: includes/trait-opti-behavior-settings-views.php:2089 2765 2765 msgid "Privacy Settings" 2766 msgstr "Paramètres de confidentialité"2766 msgstr "Paramètres de Confidentialité" 2767 2767 2768 2768 #: includes/trait-opti-behavior-settings-views.php:2091 2769 2769 msgid "Control what data is captured during recordings" 2770 msgstr "Contrôle r quelles données sont capturées pendant les enregistrements"2770 msgstr "Contrôle des données capturées" 2771 2771 2772 2772 #: includes/trait-opti-behavior-settings-views.php:2097 2773 2773 msgid "Mask All Input Fields" 2774 msgstr "Masquer tous les champs de saisie"2774 msgstr "Masquer Tous Champs" 2775 2775 2776 2776 #: includes/trait-opti-behavior-settings-views.php:2098 2777 2777 msgid "Hide all user input for privacy (recommended)" 2778 msgstr " "2778 msgstr "Masquer saisies (recommandé)" 2779 2779 "Masquer toutes les saisies utilisateur pour la confidentialité (recommandé)" 2780 2780 2781 2781 #: includes/trait-opti-behavior-settings-views.php:2110 2782 2782 msgid "Record Canvas Elements" 2783 msgstr "Enregistrer les élémentsCanvas"2783 msgstr "Enregistrer Canvas" 2784 2784 2785 2785 #: includes/trait-opti-behavior-settings-views.php:2111 2786 2786 msgid "Capture canvas and WebGL content" 2787 msgstr "Capturer le contenu canvas etWebGL"2787 msgstr "Capturer canvas/WebGL" 2788 2788 2789 2789 #: includes/trait-opti-behavior-settings-views.php:2153 2790 2790 msgid "License Status" 2791 msgstr " Licence et quota"2791 msgstr "Statut Licence" 2792 2792 2793 2793 #: includes/trait-opti-behavior-settings-views.php:2155 2794 2794 msgid "Your current license and registration status" 2795 msgstr " Votre statut de licence et d'enregistrement actuel"2795 msgstr "Statut licence et enregistrement" 2796 2796 2797 2797 #: includes/trait-opti-behavior-settings-views.php:2162 … … 2801 2801 #: includes/trait-opti-behavior-settings-views.php:2166 2802 2802 msgid "Installation ID:" 2803 msgstr "ID d'installation :"2803 msgstr "ID Installation :" 2804 2804 2805 2805 #: includes/trait-opti-behavior-settings-views.php:2170 2806 2806 msgid "License Type:" 2807 msgstr "Type de licence :"2807 msgstr "Type Licence :" 2808 2808 2809 2809 #: includes/trait-opti-behavior-settings-views.php:2171 2810 2810 msgid "Free Tier" 2811 msgstr " Niveau gratuit"2811 msgstr "Gratuit" 2812 2812 2813 2813 #: includes/trait-opti-behavior-settings-views.php:2174 … … 2817 2817 #: includes/trait-opti-behavior-settings-views.php:2181 2818 2818 msgid "Not Registered" 2819 msgstr "Non enregistré"2819 msgstr "Non Enregistré" 2820 2820 2821 2821 #: includes/trait-opti-behavior-settings-views.php:2183 … … 2829 2829 #: includes/trait-opti-behavior-settings-views.php:2192 2830 2830 msgid "Monthly Quota Usage" 2831 msgstr " Utilisation du quota mensuel"2831 msgstr "Quota Mensuel" 2832 2832 2833 2833 #: includes/trait-opti-behavior-settings-views.php:2194 2834 2834 msgid "Track your session recording usage for the current month" 2835 msgstr " Suivez votre utilisation d'enregistrement de session pour lemois en cours"2835 msgstr "Utilisation du mois en cours" 2836 2836 2837 2837 #: includes/trait-opti-behavior-settings-views.php:2208 … … 2845 2845 #: includes/trait-opti-behavior-settings-views.php:2216 2846 2846 msgid "Monthly Limit" 2847 msgstr "Limite mensuelle"2847 msgstr "Limite Mensuelle" 2848 2848 2849 2849 #: includes/trait-opti-behavior-settings-views.php:2224 … … 2866 2866 #: includes/trait-opti-behavior-settings-views.php:2241 2867 2867 msgid "Unable to retrieve quota information. Please check your API connection." 2868 msgstr "Impossible de récupérer les informations de quota. Veuillez vérifier votreconnexion API."2868 msgstr "Impossible récupérer quota. Vérifiez connexion API." 2869 2869 2870 2870 #: includes/trait-opti-behavior-settings-views.php:2252 2871 2871 msgid "Unlock unlimited recordings and advanced features" 2872 msgstr " Débloquez des enregistrements illimités et des fonctionnalités avancées"2872 msgstr "Enregistrements illimités et fonctions avancées" 2873 2873 2874 2874 #: includes/trait-opti-behavior-settings-views.php:2257 2875 2875 msgid "Pro Features:" 2876 msgstr "Fonction nalités Pro :"2876 msgstr "Fonctions Pro :" 2877 2877 2878 2878 #: includes/trait-opti-behavior-settings-views.php:2259 2879 2879 msgid "Unlimited session recordings" 2880 msgstr "Enregistrements de sessionillimités"2880 msgstr "Enregistrements illimités" 2881 2881 2882 2882 #: includes/trait-opti-behavior-settings-views.php:2260 2883 2883 msgid "Advanced heatmap analytics" 2884 msgstr "Analyses de carte de chaleuravancées"2884 msgstr "Analyses cartes avancées" 2885 2885 2886 2886 #: includes/trait-opti-behavior-settings-views.php:2261 2887 2887 msgid "Priority support" 2888 msgstr "Support prioritaire"2888 msgstr "Support Prioritaire" 2889 2889 2890 2890 #: includes/trait-opti-behavior-settings-views.php:2262 2891 2891 msgid "Extended data retention" 2892 msgstr "Rétention d e données étendue"2892 msgstr "Rétention données étendue" 2893 2893 2894 2894 #: includes/trait-opti-behavior-settings-views.php:2263 2895 2895 msgid "Custom integrations" 2896 msgstr "Intégrations personnalisées"2896 msgstr "Intégrations Personnalisées" 2897 2897 2898 2898 #: Opti-Behavior.php:40 … … 2999 2999 #: includes/class-opti-behavior-session-recording.php 3000 3000 msgid "New visitor" 3001 msgstr "Nouveau visiteur"3001 msgstr "Nouveau Visiteur" 3002 3002 3003 3003 #: includes/class-opti-behavior-session-recording.php … … 3032 3032 msgid "Delete Recording" 3033 3033 msgstr "Supprimer l'enregistrement" 3034 3035 #: admin/class-opti-behavior-heatmap-admin-settings.php:295 3036 msgid "Delete all heatmap data? This cannot be undone." 3037 msgstr "Supprimer toutes les données de carte de chaleur ? Cette action est irréversible." 3038 3039 #: admin/recordings-page.php:22 3040 msgid "Watch real user sessions to understand behavior patterns and identify UX issues." 3041 msgstr "Regardez les sessions pour comprendre le comportement et identifier les problèmes UX." 3042 3043 #: includes/class-opti-behavior-session-encryption.php:407 3044 msgid "You have reached the free tier limit of 500 session recordings per month. Please upgrade to continue recording sessions." 3045 msgstr "Vous avez atteint la limite gratuite de 500 enregistrements de session par mois. Veuillez passer à la version Pro pour continuer à enregistrer des sessions." 3046 3047 #: includes/trait-opti-behavior-ai-insights-views.php:53 3048 msgid "AI-Powered Analytics Insights" 3049 msgstr "Analyses basées sur l'IA" 3050 3051 #: includes/trait-opti-behavior-ai-insights-views.php:54 3052 msgid "The Future of Website Optimization is Here" 3053 msgstr "L'avenir de l'optimisation web est ici" 3054 3055 #: includes/trait-opti-behavior-ai-insights-views.php:58 3056 msgid "Coming Soon" 3057 msgstr "Bientôt Disponible" 3058 3059 #: includes/trait-opti-behavior-ai-insights-views.php:96 3060 msgid "Next-Level Analytics with Artificial Intelligence" 3061 msgstr "Analyses de nouvelle génération avec intelligence artificielle" 3062 3063 #: includes/trait-opti-behavior-ai-insights-views.php:98 3064 msgid "This is a revolutionary new project that will take your Analytics to the next level by using AI to analyze everything happening on your website. We help you understand what works well to optimize it and achieve more performance in your business." 3065 msgstr "Il s'agit d'un nouveau projet révolutionnaire qui amènera vos analyses au niveau supérieur en utilisant l'IA pour analyser tout ce qui se passe sur votre site web. Nous vous aidons à comprendre ce qui fonctionne bien pour l'optimiser et obtenir plus de performance dans votre entreprise." 3066 3067 #: includes/trait-opti-behavior-ai-insights-views.php:106 3068 msgid "Smart Analysis" 3069 msgstr "Analyse Intelligente" 3070 3071 #: includes/trait-opti-behavior-ai-insights-views.php:107 3072 msgid "AI identifies patterns and trends in user behavior that humans might miss, providing actionable insights automatically." 3073 msgstr "L'IA identifie des modèles et tendances dans le comportement des utilisateurs que les humains pourraient manquer, fournissant automatiquement des informations exploitables." 3074 3075 #: includes/trait-opti-behavior-ai-insights-views.php:113 3076 msgid "Automatically detect problems affecting user experience, conversion rates, and engagement before they impact your business." 3077 msgstr "Détectez automatiquement les problèmes affectant l'expérience utilisateur, les taux de conversion et l'engagement avant qu'ils n'impactent votre entreprise." 3078 3079 #: includes/trait-opti-behavior-ai-insights-views.php:118 3080 msgid "Auto-Fix & Suggestions" 3081 msgstr "Corrections Automatiques et Suggestions" 3082 3083 #: includes/trait-opti-behavior-ai-insights-views.php:119 3084 msgid "Get intelligent recommendations and automatic fixes to improve traffic, sales, engagement time, and overall performance." 3085 msgstr "Obtenez des recommandations intelligentes et des corrections automatiques pour améliorer le trafic, les ventes, le temps d'engagement et la performance globale." 3086 3087 #: includes/trait-opti-behavior-ai-insights-views.php:124 3088 msgid "Performance Optimization" 3089 msgstr "Optimisation des Performances" 3090 3091 #: includes/trait-opti-behavior-ai-insights-views.php:125 3092 msgid "Optimize your website for maximum conversions, longer session times, and increased revenue with AI-driven strategies." 3093 msgstr "Optimisez votre site web pour des conversions maximales, des temps de session plus longs et des revenus accrus avec des stratégies basées sur l'IA." 3094 3095 #: includes/trait-opti-behavior-ai-insights-views.php:130 3096 msgid "UX Enhancement" 3097 msgstr "Amélioration de l'UX" 3098 3099 #: includes/trait-opti-behavior-ai-insights-views.php:131 3100 msgid "Improve user experience based on real behavioral data and AI predictions of what will work best for your audience." 3101 msgstr "Améliorez l'expérience utilisateur en vous basant sur des données comportementales réelles et les prédictions de l'IA sur ce qui fonctionnera le mieux pour votre audience." 3102 3103 #: includes/trait-opti-behavior-ai-insights-views.php:137 3104 msgid "Forecast trends and user behavior to stay ahead of the curve and make data-driven decisions with confidence." 3105 msgstr "Prévoyez les tendances et le comportement des utilisateurs pour garder une longueur d'avance et prendre des décisions basées sur les données en toute confiance." 3106 3107 #: includes/trait-opti-behavior-ai-insights-views.php:143 3108 msgid "What Our AI Will Analyze" 3109 msgstr "Ce que Notre IA Analysera" 3110 3111 #: includes/trait-opti-behavior-ai-insights-views.php:151 3112 msgid "Sales Funnels" 3113 msgstr "Tunnels de Vente" 3114 3115 #: includes/trait-opti-behavior-ai-insights-views.php:155 3116 msgid "Engagement Time" 3117 msgstr "Temps d'Engagement" 3118 3119 #: includes/trait-opti-behavior-ai-insights-views.php:163 3120 msgid "Device Performance" 3121 msgstr "Performance par Appareil" 3122 3123 #: includes/trait-opti-behavior-ai-insights-views.php:167 3124 msgid "Geographic Trends" 3125 msgstr "Tendances Géographiques" 3126 3127 #: includes/trait-opti-behavior-ai-insights-views.php:171 3128 msgid "User Journeys" 3129 msgstr "Parcours Utilisateurs" 3130 3131 #: includes/trait-opti-behavior-ai-insights-views.php:175 3132 msgid "Revenue Impact" 3133 msgstr "Impact sur les Revenus" 3134 3135 #: includes/trait-opti-behavior-ai-insights-views.php:184 3136 msgid "Help Shape the Future!" 3137 msgstr "Aidez à façonner l'avenir !" 3138 3139 #: includes/trait-opti-behavior-ai-insights-views.php:186 3140 msgid "We're building this amazing AI-powered feature and we'd love to hear from you! Your experience and feedback are invaluable in making this the best analytics tool possible." 3141 msgstr "Nous construisons cette fonctionnalité incroyable basée sur l'IA et nous aimerions avoir votre avis ! Votre expérience et vos retours sont inestimables pour faire de cet outil le meilleur possible." 3142 3143 #: includes/trait-opti-behavior-ai-insights-views.php:191 3144 msgid "Share Your Ideas" 3145 msgstr "Partagez vos idées" 3146 3147 #: includes/trait-opti-behavior-ai-insights-views.php:199 3148 msgid "%1$sEarly adopters%2$s who share feedback will get %3$sexclusive early access%4$s when we launch! 🎉" 3149 msgstr "%1$sLes premiers utilisateurs%2$s qui partagent leurs retours auront %3$sun accès anticipé exclusif%4$s lors du lancement ! 🎉" 3150 3151 #: includes/trait-opti-behavior-ai-insights-views.php:212 3152 msgid "Development Roadmap" 3153 msgstr "Plan de Développement" 3154 3155 #: includes/trait-opti-behavior-ai-insights-views.php:217 3156 msgid "Phase 1: Foundation" 3157 msgstr "Phase 1 : Fondation" 3158 3159 #: includes/trait-opti-behavior-ai-insights-views.php:218 3160 msgid "Advanced analytics data collection and processing infrastructure" 3161 msgstr "Infrastructure de Collecte et de Traitement de Données" 3162 3163 #: includes/trait-opti-behavior-ai-insights-views.php:224 3164 msgid "Phase 2: AI Integration" 3165 msgstr "Phase 2 : Intégration de l'IA" 3166 3167 #: includes/trait-opti-behavior-ai-insights-views.php:225 3168 msgid "Machine learning models for pattern recognition and insights" 3169 msgstr "Modèles d'Apprentissage pour Reconnaissance de Modèles" 3170 3171 #: includes/trait-opti-behavior-ai-insights-views.php:231 3172 msgid "Phase 3: Auto-Optimization" 3173 msgstr "Phase 3 : Auto-optimisation" 3174 3175 #: includes/trait-opti-behavior-ai-insights-views.php:232 3176 msgid "Automated fixes and intelligent recommendations engine" 3177 msgstr "Moteur de corrections automatiques et de recommandations intelligentes" 3178 3179 #: includes/trait-opti-behavior-ai-insights-views.php:238 3180 msgid "Phase 4: Launch" 3181 msgstr "Phase 4 : Lancement" 3182 3183 #: includes/trait-opti-behavior-ai-insights-views.php:239 3184 msgid "Full AI-powered analytics suite with predictive capabilities" 3185 msgstr "Suite Complète d'Analyses IA avec Capacités Prédictives" 3186 3187 #: includes/trait-opti-behavior-ajax-handlers.php:88 3188 msgid "Unauthorized" 3189 msgstr "Non autorisé" 3190 3191 #: includes/trait-opti-behavior-ajax-handlers.php:534 3192 msgid "Recordings directory not found" 3193 msgstr "Répertoire d'enregistrements introuvable" 3194 3195 #: includes/trait-opti-behavior-dashboard-views.php:41 3196 msgid "Real-time insights and user behavior analytics" 3197 msgstr "Analyses en Temps Réel" 3198 3199 #: includes/trait-opti-behavior-dashboard-views.php:856 3200 msgid "Human" 3201 msgstr "Humain" 3202 3203 #: includes/trait-opti-behavior-dashboard-views.php:856 3204 msgid "Spam" 3205 msgstr "Spam" 3206 3207 #: includes/trait-opti-behavior-maintenance.php:88 3208 msgid "All opti-behavior Analytics tables were emptied successfully." 3209 msgstr "Toutes les tables d'analyses opti-behavior ont été vidées avec succès." 3210 3211 #: includes/trait-opti-behavior-sessions-views.php:40 3212 msgid "Recordings (incl. Alarming Behavior) Remaining:" 3213 msgstr "Enregistrements restants (y compris comportements alarmants) :" 3214 3215 #: includes/trait-opti-behavior-sessions-views.php:57 3216 msgid "Install Date → Today" 3217 msgstr "Date d'installation → Aujourd'hui" 3218 3219 #: includes/trait-opti-behavior-sessions-views.php:82 3220 msgid "Select ∨" 3221 msgstr "Sélectionner ∨" 3222 3223 #: includes/trait-opti-behavior-sessions-views.php:84 3224 msgid "Select None" 3225 msgstr "Ne rien sélectionner" 3226 3227 #: includes/trait-opti-behavior-settings-views.php:123 3228 msgid "Configure opti-behavior: Heatmap, tracking, Data and display options" 3229 msgstr "Configurer opti-behavior : Options de carte de chaleur, suivi, données et affichage" 3230 3231 #: includes/trait-opti-behavior-settings-views.php:248 3232 msgid "Configure how heatmap data is collected, tracked, and displayed" 3233 msgstr "Configurez comment les données de carte de chaleur sont collectées, suivies et affichées" 3234 3235 #: includes/trait-opti-behavior-settings-views.php:255 3236 msgid "Controls which screen sizes are tracked for heatmap data" 3237 msgstr "Contrôle quelles tailles d'écran sont suivies pour les données de carte de chaleur" 3238 3239 #: includes/trait-opti-behavior-settings-views.php:276 3240 msgid "Track category pages, archives, and other non-singular pages" 3241 msgstr "Suivre les pages de catégories, archives et autres pages non singulières" 3242 3243 #: includes/trait-opti-behavior-settings-views.php:415 3244 msgid "Maximum number of data points to display on heatmaps" 3245 msgstr "Nombre maximum de points de données à afficher sur les cartes de chaleur" 3246 3247 #: includes/trait-opti-behavior-settings-views.php:446 3248 msgid "Show interaction count information on heatmaps" 3249 msgstr "Afficher les informations de comptage des interactions sur les cartes de chaleur" 3250 3251 #: includes/trait-opti-behavior-settings-views.php:525 3252 msgid "Permanently delete analytics data from your database. These actions cannot be undone." 3253 msgstr "Supprimer définitivement les données d'analyse de votre base de données. Ces actions ne peuvent pas être annulées." 3254 3255 #: includes/trait-opti-behavior-settings-views.php:530 3256 msgid "This will permanently delete ALL analytics data from your database. This cannot be undone." 3257 msgstr "Ceci supprimera définitivement TOUTES les données d'analyse de votre base de données. Cette action est irréversible." 3258 3259 #: includes/trait-opti-behavior-settings-views.php:540 3260 msgid "This will permanently delete ALL analytics data. Are you absolutely sure?" 3261 msgstr "Ceci supprimera définitivement TOUTES les données d'analyse. Êtes-vous absolument sûr ?" 3262 3263 #: includes/trait-opti-behavior-settings-views.php:591 3264 msgid "Configure what happens when you uninstall this plugin. Choose whether to keep or remove all data and database tables." 3265 msgstr "Configurez ce qui se passe lorsque vous désinstallez ce plugin. Choisissez de conserver ou de supprimer toutes les données et tables de base de données." 3266 3267 #: includes/trait-opti-behavior-settings-views.php:596 3268 msgid "These settings determine what happens when you uninstall the plugin." 3269 msgstr "Ces paramètres déterminent ce qui se passe lorsque vous désinstallez le plugin." 3270 3271 #: includes/trait-opti-behavior-settings-views.php:597 3272 msgid "If you enable \"Delete on Uninstall\", the following will be permanently removed:" 3273 msgstr "Si vous activez \"Supprimer à la désinstallation\", les éléments suivants seront définitivement supprimés :" 3274 3275 #: includes/trait-opti-behavior-settings-views.php:599 3276 msgid "All database tables (events, pages, sessions, analytics)" 3277 msgstr "Toutes les tables de base de données (événements, pages, sessions, analyses)" 3278 3279 #: includes/trait-opti-behavior-settings-views.php:617 3280 msgid "Delete all data and tables on plugin uninstall" 3281 msgstr "Supprimer toutes les données et tables lors de la désinstallation du plugin" 3282 3283 #: includes/trait-opti-behavior-settings-views.php:621 3284 msgid "When enabled, all plugin data and database tables will be permanently deleted when you uninstall the plugin. Leave unchecked if you plan to reinstall the plugin later and want to keep your data." 3285 msgstr "Lorsqu'activé, toutes les données du plugin et tables de base de données seront définitivement supprimées lors de la désinstallation. Laissez décoché si vous prévoyez de réinstaller le plugin plus tard et souhaitez conserver vos données." 3286 3287 #: includes/trait-opti-behavior-settings-views.php:663 3288 msgid "Select your preferred language for the Opti-Behavior plugin admin interface." 3289 msgstr "Sélectionnez votre langue préférée pour l'interface d'administration du plugin Opti-Behavior." 3290 3291 #: includes/trait-opti-behavior-settings-views.php:672 3292 #: includes/trait-opti-behavior-settings-views.php:741 3293 msgid "Language settings saved successfully. The new language will be applied on the next page load." 3294 msgstr "Paramètres de langue enregistrés avec succès. La nouvelle langue sera appliquée au prochain chargement de page." 3295 3296 #: includes/trait-opti-behavior-settings-views.php:697 3297 msgid "This setting only affects the Opti-Behavior plugin admin interface. It does not change the language of your WordPress admin or other plugins." 3298 msgstr "Ce paramètre affecte uniquement l'interface d'administration du plugin Opti-Behavior. Il ne modifie pas la langue de votre administration WordPress ou d'autres plugins." 3299 3300 #: includes/trait-opti-behavior-settings-views.php:875 3301 msgid "✅ Data Recovery Completed!" 3302 msgstr "✅ Récupération de données terminée !" 3303 3304 #: includes/trait-opti-behavior-settings-views.php:876 3305 msgid "Found and recovered: %s events, %s accessible heatmaps." 3306 msgstr "Trouvé et récupéré : %s événements, %s cartes de chaleur accessibles." 3307 3308 #: includes/trait-opti-behavior-settings-views.php:878 3309 msgid "Issues fixed: %s" 3310 msgstr "Problèmes résolus : %s" 3311 3312 #: includes/trait-opti-behavior-settings-views.php:886 3313 msgid "✅ Data Check Completed!" 3314 msgstr "✅ Vérification des données terminée !" 3315 3316 #: includes/trait-opti-behavior-settings-views.php:887 3317 msgid "No issues detected. Your data is healthy with %s events." 3318 msgstr "Aucun problème détecté. Vos données sont saines avec %s événements." 3319 3320 #: includes/trait-opti-behavior-settings-views.php:920 3321 msgid "This plugin includes automatic data protection that prevents data loss when the plugin is disabled, renamed, or moved. The system runs integrity checks and automatically recovers your data if any issues are detected." 3322 msgstr "Ce plugin inclut une protection automatique des données qui empêche la perte de données lorsque le plugin est désactivé, renommé ou déplacé. Le système effectue des vérifications d'intégrité et récupère automatiquement vos données si des problèmes sont détectés." 3323 3324 #: includes/trait-opti-behavior-settings-views.php:976 3325 msgid "Click this button if you suspect data integrity issues. The system will scan and automatically fix any problems." 3326 msgstr "Cliquez sur ce bouton si vous suspectez des problèmes d'intégrité des données. Le système analysera et corrigera automatiquement les problèmes." 3327 3328 #: includes/trait-opti-behavior-settings-views.php:1001 3329 msgid "Configure debug logging for PHP and JavaScript. Enable debugging to troubleshoot issues and monitor plugin behavior. Logs are stored securely and can be viewed or downloaded below." 3330 msgstr "Configurez la journalisation de débogage pour PHP et JavaScript. Activez le débogage pour résoudre les problèmes et surveiller le comportement du plugin. Les journaux sont stockés en toute sécurité et peuvent être consultés ou téléchargés ci-dessous." 3331 3332 #: includes/trait-opti-behavior-settings-views.php:1318 3333 msgid "Choose how to store recordings and events data" 3334 msgstr "Choisissez comment stocker les enregistrements et les données d'événements" 3335 3336 #: includes/trait-opti-behavior-settings-views.php:1325 3337 msgid "File storage recommended for high-traffic sites (30K+ visits/day)" 3338 msgstr "Stockage de fichiers recommandé pour les sites à fort trafic (30K+ visites/jour)" 3339 3340 #: includes/trait-opti-behavior-settings-views.php:1367 3341 msgid "Configure how long to keep data before automatic deletion" 3342 msgstr "Configurez la durée de conservation des données avant suppression automatique" 3343 3344 #: includes/trait-opti-behavior-settings-views.php:1379 3345 msgid "days" 3346 msgstr "jours" 3347 3348 #: includes/trait-opti-behavior-settings-views.php:1415 3349 msgid "Delete oldest files when this limit is exceeded" 3350 msgstr "Supprimer les fichiers les plus anciens lorsque cette limite est dépassée" 3351 3352 #: includes/trait-opti-behavior-settings-views.php:1465 3353 msgid "Remove all recording files that don't have corresponding database entries" 3354 msgstr "Supprimer tous les fichiers d'enregistrement qui n'ont pas d'entrées de base de données correspondantes" 3355 3356 #: includes/trait-opti-behavior-settings-views.php:1480 3357 msgid "Clean up recording files that have no database records" 3358 msgstr "Nettoyer les fichiers d'enregistrement qui n'ont pas d'enregistrements de base de données" 3359 3360 #: includes/trait-opti-behavior-settings-views.php:1495 3361 msgid "This will permanently delete all .json.gz files in the recordings directory that don't have matching database records." 3362 msgstr "Ceci supprimera définitivement tous les fichiers .json.gz du répertoire d'enregistrements qui n'ont pas d'enregistrements de base de données correspondants." 3363 3364 #: includes/trait-opti-behavior-settings-views.php:1558 3365 msgid "Upgrade to unlock advanced file storage capabilities including:" 3366 msgstr "Passez à la version Pro pour débloquer les capacités avancées de stockage de fichiers, notamment :" 3367 3368 #: includes/trait-opti-behavior-settings-views.php:1561 3369 msgid "File-based storage to prevent database bloat" 3370 msgstr "Stockage basé sur des fichiers pour éviter l'encombrement de la base de données" 3371 3372 #: includes/trait-opti-behavior-settings-views.php:1739 3373 msgid "Configure dashboard behavior, traffic classification, and user intent detection rules." 3374 msgstr "Configurez le comportement du tableau de bord, la classification du trafic et les règles de détection d'intention utilisateur." 3375 3376 #: includes/trait-opti-behavior-settings-views.php:1789 3377 msgid "Configure how Opti-Behavior classifies different types of traffic." 3378 msgstr "Configurez comment Opti-Behavior classe les différents types de trafic." 3379 3380 #: includes/trait-opti-behavior-settings-views.php:1799 3381 msgid "Detect and classify legitimate bots (search engines, social crawlers, SEO tools)." 3382 msgstr "Détecter et classifier les bots légitimes (moteurs de recherche, robots sociaux, outils SEO)." 3383 3384 #: includes/trait-opti-behavior-settings-views.php:1810 3385 msgid "Detect headless browsers, automation tools, and scripts (Selenium, Puppeteer, curl, etc.)." 3386 msgstr "Détecter les navigateurs sans interface, outils d'automatisation et scripts (Selenium, Puppeteer, curl, etc.)." 3387 3388 #: includes/trait-opti-behavior-settings-views.php:1821 3389 msgid "Detect low-quality traffic based on session behavior patterns." 3390 msgstr "Détecter le trafic de faible qualité basé sur les modèles de comportement de session." 3391 3392 #: includes/trait-opti-behavior-settings-views.php:1830 3393 msgid "Sessions shorter than this duration may be classified as spam." 3394 msgstr "Les sessions plus courtes que cette durée peuvent être classées comme spam." 3395 3396 #: includes/trait-opti-behavior-settings-views.php:1839 3397 msgid "Bounce rate threshold for spam detection (100% = immediate exit)." 3398 msgstr "Seuil de taux de rebond pour la détection de spam (100% = sortie immédiate)." 3399 3400 #: includes/trait-opti-behavior-settings-views.php:1847 3401 msgid "Enter custom user agent patterns to detect as bots (one per line). Example: MyCustomBot" 3402 msgstr "Entrez des modèles d'agent utilisateur personnalisés à détecter comme bots (un par ligne). Exemple : MyCustomBot" 3403 3404 #: includes/trait-opti-behavior-settings-views.php:1886 3405 msgid "Define rules for classifying user intent levels based on engagement metrics." 3406 msgstr "Définissez des règles pour classifier les niveaux d'intention utilisateur basés sur les métriques d'engagement." 3407 3408 #: includes/trait-opti-behavior-settings-views.php:1892 3409 msgid "Low Intent" 3410 msgstr "Faible Intention" 3411 3412 #: includes/trait-opti-behavior-settings-views.php:1901 3413 msgid "Maximum time spent on page for low intent classification." 3414 msgstr "Temps maximum passé sur la page pour la classification d'intention faible." 3415 3416 #: includes/trait-opti-behavior-settings-views.php:1905 3417 #: includes/trait-opti-behavior-settings-views.php:1942 3418 #: includes/trait-opti-behavior-settings-views.php:1979 3419 msgid "Number of Clicks" 3420 msgstr "Nombre de clics" 3421 3422 #: includes/trait-opti-behavior-settings-views.php:1910 3423 msgid "Maximum number of clicks for low intent classification." 3424 msgstr "Nombre maximum de clics pour la classification d'intention faible." 3425 3426 #: includes/trait-opti-behavior-settings-views.php:1914 3427 #: includes/trait-opti-behavior-settings-views.php:1951 3428 #: includes/trait-opti-behavior-settings-views.php:1988 3429 msgid "Scroll Depth (%)" 3430 msgstr "Profondeur de Défilement (%)" 3431 3432 #: includes/trait-opti-behavior-settings-views.php:1919 3433 msgid "Maximum scroll depth percentage for low intent classification." 3434 msgstr "Pourcentage maximum de profondeur de défilement pour la classification d'intention faible." 3435 3436 #: includes/trait-opti-behavior-settings-views.php:1929 3437 msgid "Medium Intent" 3438 msgstr "Intention Moyenne" 3439 3440 #: includes/trait-opti-behavior-settings-views.php:1938 3441 msgid "Minimum time spent on page for medium intent classification." 3442 msgstr "Temps minimum passé sur la page pour la classification d'intention moyenne." 3443 3444 #: includes/trait-opti-behavior-settings-views.php:1947 3445 msgid "Minimum number of clicks for medium intent classification." 3446 msgstr "Nombre minimum de clics pour la classification d'intention moyenne." 3447 3448 #: includes/trait-opti-behavior-settings-views.php:1956 3449 msgid "Minimum scroll depth percentage for medium intent classification." 3450 msgstr "Pourcentage minimum de profondeur de défilement pour la classification d'intention moyenne." 3451 3452 #: includes/trait-opti-behavior-settings-views.php:1966 3453 msgid "High Intent" 3454 msgstr "Forte Intention" 3455 3456 #: includes/trait-opti-behavior-settings-views.php:1975 3457 msgid "Minimum time spent on page for high intent classification." 3458 msgstr "Temps minimum passé sur la page pour la classification d'intention élevée." 3459 3460 #: includes/trait-opti-behavior-settings-views.php:1984 3461 msgid "Minimum number of clicks for high intent classification." 3462 msgstr "Nombre minimum de clics pour la classification d'intention élevée." 3463 3464 #: includes/trait-opti-behavior-settings-views.php:1993 3465 msgid "Minimum scroll depth percentage for high intent classification." 3466 msgstr "Pourcentage minimum de profondeur de défilement pour la classification d'intention élevée." 3467 3468 #: includes/trait-opti-behavior-settings-views.php:2040 3469 msgid "Configure how session recordings are captured and stored" 3470 msgstr "Configuration capture et stockage" 3471 3472 #: includes/trait-opti-behavior-settings-views.php:2073 3473 msgid "How often to capture mouse movements (lower = more data)" 3474 msgstr "Fréquence capture (+ bas = + données)" 3475 3476 #: includes/trait-opti-behavior-settings-views.php:2098 3477 msgid "Hide all user input for privacy (recommended)" 3478 msgstr "Masquer saisies (recommandé)" 3479 3480 #: includes/trait-opti-behavior-settings-views.php:2183 3481 msgid "Your installation is not registered. Session recordings will use offline encryption only." 3482 msgstr "Installation non enregistrée. Chiffrement hors ligne uniquement." 3483 3484 #: includes/trait-opti-behavior-settings-views.php:2230 3485 msgid "You have exceeded your monthly quota! New recordings will not be saved until next month or you upgrade to Pro." 3486 msgstr "Quota dépassé ! Enregistrements bloqués jusqu'au mois prochain ou mise à niveau Pro." 3487 3488 #: includes/trait-opti-behavior-settings-views.php:2235 3489 msgid "You're running low on quota. Consider upgrading to Pro for unlimited recordings." 3490 msgstr "Quota faible. Envisagez Pro pour enregistrements illimités." 3491 3492 #: Opti-Behavior.php:40 3493 msgid "Opti-Behavior requires PHP version %1$s or higher. You are running PHP version %2$s. Please upgrade PHP to activate this plugin." 3494 msgstr "Opti-Behavior nécessite PHP version %1$s ou supérieure. Vous utilisez PHP version %2$s. Veuillez mettre à jour PHP pour activer ce plugin." 3495 3496 #: Opti-Behavior.php:66 3497 msgid "Fail to activate. Another version of opti-behavior Heatmap is already active." 3498 msgstr "Échec de l'activation. Une autre version d'opti-behavior Heatmap est déjà active." 3499 3500 #: views/heatmaps-views.php:122 3501 msgid "As visitors interact, this table will populate." 3502 msgstr "Au fur et à mesure que les visiteurs interagissent, ce tableau se remplira." 3503 3504 #: admin/class-opti-behavior-heatmap-dashboard.php:282 3505 msgid "Mobile" 3506 msgstr "Mobile" 3507 3508 #: admin/class-opti-behavior-heatmap-dashboard.php:283 3509 msgid "PC" 3510 msgstr "PC" 3511 3512 #: admin/class-opti-behavior-heatmap-dashboard.php:293 3513 msgid "No page data available" 3514 msgstr "Aucune donnée de page disponible" 3515 3516 #: admin/class-opti-behavior-heatmap-dashboard.php:294 3517 msgid "No visitor data available" 3518 msgstr "Aucune donnée de visiteur disponible" 3519 3520 #: admin/class-opti-behavior-heatmap-dashboard.php:295 3521 msgid "No browser data available" 3522 msgstr "Aucune Donnée de Navigateur" 3523 3524 #: admin/class-opti-behavior-heatmap-dashboard.php:296 3525 msgid "No device data available" 3526 msgstr "Aucune donnée d'appareil disponible" 3527 3528 #: admin/class-opti-behavior-heatmap-dashboard.php:297 3529 msgid "Data will appear as visitors interact with your site." 3530 msgstr "Les données apparaîtront lorsque les visiteurs interagiront avec votre site." 3531 3532 #: admin/class-opti-behavior-heatmap-dashboard.php:297 3533 msgid "No data yet" 3534 msgstr "Pas encore de données" 3535 3536 #: includes/class-opti-behavior-heatmap-analytics.php:867 3537 msgid "Home Page" 3538 msgstr "Page d'accueil" 3539 3540 #: views/dashboard-views.php:74 3541 msgid "📊 Analytics Dashboard" 3542 msgstr "📊 Tableau de bord analytique" 3543 3544 #: views/dashboard-views.php:76 3545 msgid "Real-time insights and user behavior analytics" 3546 msgstr "Analyses en Temps Réel" 3547 3548 #: views/dashboard-views.php:92 3549 msgid "Apply" 3550 msgstr "Appliquer" 3551 3552 #: views/dashboard-views.php:96 3553 msgid "Refresh" 3554 msgstr "Actualiser" 3555 3556 #: views/dashboard-views.php:117 3557 msgid "%s%% vs last period" 3558 msgstr "%s%% vs période précédente" 3559 3560 #: views/dashboard-views.php:198 3561 msgid "Traffic Overview" 3562 msgstr "Aperçu du Trafic" 3563 3564 #: views/dashboard-views.php:209 3565 msgid "Browsers" 3566 msgstr "Navigateurs" 3567 3568 #: views/dashboard-views.php:219 3569 msgid "Device Types" 3570 msgstr "Types d'Appareils" 3571 3572 #: views/dashboard-views.php:229 3573 msgid "Operating Systems" 3574 msgstr "Systèmes d'Exploitation" 3575 3576 #: views/dashboard-views.php:241 3577 msgid "User Intent" 3578 msgstr "Intention de l'Utilisateur" 3579 3580 #: views/dashboard-views.php:264 3581 msgid "Daily Freq" 3582 msgstr "Fréq. quotidienne" 3583 3584 #: views/dashboard-views.php:265 3585 msgid "Avg Session" 3586 msgstr "Session moy." 3587 3588 #: views/dashboard-views.php:268 3589 msgid "Pages/Sess" 3590 msgstr "Pages/Sess" 3591 3592 #: views/dashboard-views.php:289 3593 msgid "Top Countries" 3594 msgstr "Principaux Pays" 3595 3596 #: views/dashboard-views.php:300 3597 msgid "Live" 3598 msgstr "En Direct" 3599 3600 #: views/dashboard-views.php:301 3601 msgid "Real-time Visitors" 3602 msgstr "Visiteurs en Temps Réel" 3603 3604 #: views/dashboard-views.php:317 3605 msgid "—" 3606 msgstr "—" 3607 3608 #: views/dashboard-views.php:333 3609 msgid "No active visitors right now" 3610 msgstr "Aucun Visiteur Actif" 3611 3612 #: views/dashboard-views.php:334 3613 msgid "Traffic updates in real-time." 3614 msgstr "Le Trafic se Met à Jour en Temps Réel." 3615 3616 #: views/dashboard-views.php:343 3617 msgid "Real-time Visitor Map" 3618 msgstr "Carte des Visiteurs en Temps Réel" 3619 3620 #: views/dashboard-views.php:358 3621 msgid "Top Pages" 3622 msgstr "Pages Principales" 3623 3624 #: views/dashboard-views.php:366 3625 msgid "No page views yet" 3626 msgstr "Aucune page vue pour le moment" 3627 3628 #: views/dashboard-views.php:367 3629 msgid "Once visitors view pages, you'll see them here." 3630 msgstr "Les Pages Vues Apparaîtront Ici." 3631 3632 #: views/dashboard-views.php:405 3633 msgid "PC" 3634 msgstr "PC" 3635 3636 #: views/dashboard-views.php:409 3637 msgid "Mobile" 3638 msgstr "Mobile" 3639 3640 #: views/dashboard-views.php:446 3641 msgid "Top Referrers" 3642 msgstr "Principaux Référents" 3643 3644 #: includes/trait-opti-behavior-dashboard-views.php:257 3645 msgid "No engaged users for this period" 3646 msgstr "Aucun Utilisateur Engagé pour cette Période" 3647 3648 #: includes/trait-opti-behavior-dashboard-views.php:258 3649 msgid "As visitors engage more, you'll see them ranked here." 3650 msgstr "Lorsque les visiteurs s'engagent davantage, vous les verrez classés ici." 3651 3652 #: includes/trait-opti-behavior-dashboard-views.php:279 3653 msgid "Once visitors view pages, you will see them here." 3654 msgstr "Les Pages Vues Apparaîtront Ici." 3655 3656 #: includes/trait-opti-behavior-dashboard-views.php:438 3657 msgid "No referrer data available" 3658 msgstr "Aucune Donnée de Référent" 3659 3660 #: includes/trait-opti-behavior-dashboard-views.php:439 3661 #: includes/trait-opti-behavior-dashboard-views.php:484 3662 #: includes/trait-opti-behavior-dashboard-views.php:564 3663 #: includes/trait-opti-behavior-dashboard-views.php:901 3664 #: includes/trait-opti-behavior-dashboard-views.php:1165 3665 #: includes/trait-opti-behavior-dashboard-views.php:1200 3666 msgid "Try broadening the date range or check back later." 3667 msgstr "Élargir la Période ou Revenir Plus Tard." 3668 3669 #: includes/trait-opti-behavior-dashboard-views.php:1158 3670 msgid "New vs Returning Visitors" 3671 msgstr "Nouveaux vs Visiteurs Récurrents" 3672 3673 msgid "New Visitors" 3674 msgstr "Nouveaux Visiteurs" 3675 3676 msgid "Returning Visitors" 3677 msgstr "Visiteurs Récurrents" 3678 3679 #: includes/trait-opti-behavior-dashboard-views.php:1193 3680 msgid "Visited Directories" 3681 msgstr "Répertoires Visités" 3682 3683 msgid "Posts" 3684 msgstr "Articles" 3685 3686 #: includes/trait-opti-behavior-dashboard-views.php:1227 3687 msgid "Visitor Authentication" 3688 msgstr "Authentification des Visiteurs" 3689 3690 msgid "Total Visitors" 3691 msgstr "Visiteurs Totaux" 3692 3693 msgid "Logged In Visitors" 3694 msgstr "Visiteurs Connectés" 3695 3696 msgid "New Registrations" 3697 msgstr "Nouvelles Inscriptions" 3698 3699 msgid "No country data available" 3700 msgstr "Aucune Donnée de Pays" 3701 3702 msgid "Try broadening the date range or check back later." 3703 msgstr "Élargir la Période ou Revenir Plus Tard." 3704 3705 msgid "No screen resolution data available" 3706 msgstr "Aucune Donnée de Résolution" 3707 3708 msgid "Page" 3709 msgstr "Page" 3710 3711 msgid "Interactions" 3712 msgstr "Interactions" 3713 3714 msgid "Sessions" 3715 msgstr "Sessions" 3716 3717 msgid "Device Split" 3718 msgstr "Répartition des appareils" 3719 3720 msgid "Last Updated" 3721 msgstr "Dernière mise à jour" 3722 3723 msgid "Actions" 3724 msgstr "Actions" 3725 3726 #. translators: %s: number of desktop views 3727 msgid "Desktop (%s)" 3728 msgstr "Bureau (%s)" 3729 3730 #. translators: %s: number of mobile views 3731 msgid "Mobile (%s)" 3732 msgstr "Mobile (%s)" 3733 3734 msgid "Open desktop heatmap" 3735 msgstr "Ouvrir la carte de chaleur bureau" 3736 3737 msgid "Open mobile heatmap" 3738 msgstr "Ouvrir la carte de chaleur mobile" 3739 3740 msgid "No heatmaps available." 3741 msgstr "Aucune carte de chaleur disponible." 3742 3743 #. translators: %1$s: start range, %2$s: end range, %3$s: total items, %4$s: current page, %5$s: total pages 3744 msgid "Showing %1$s–%2$s of %3$s · Page %4$s / %5$s" 3745 msgstr "Affichage de %1$s–%2$s sur %3$s · Page %4$s / %5$s" 3746 3747 msgid "First" 3748 msgstr "Premier" 3749 3750 msgid "Prev" 3751 msgstr "Précédent" 3752 3753 msgid "Next" 3754 msgstr "Suivant" 3755 3756 msgid "Last" 3757 msgstr "Dernier" 3758 3759 msgid "Total Heatmaps" 3760 msgstr "Total des Cartes de Chaleur" 3761 3762 msgid "Avg. Time on Page" 3763 msgstr "Temps Moy. Page" 3764 3765 msgid "Hottest Page" 3766 msgstr "Page la Plus Chaude" 3767 3768 msgid "Click-through Rate" 3769 msgstr "Taux de Clic" 3770 3771 msgid "Available Heatmaps" 3772 msgstr "Cartes de Chaleur Disponibles" 3773 3774 msgid "View detailed heatmap analysis" 3775 msgstr "Voir l'analyse détaillée de la carte de chaleur" 3776 3777 msgid "Back to Heatmaps" 3778 msgstr "Retour aux Cartes" 3779 3780 msgid "recordings" 3781 msgstr "enregistrements" 3782 3783 msgid "Refresh" 3784 msgstr "Actualiser" 3785 3786 msgid "Desktop" 3787 msgstr "Bureau" 3788 3789 msgid "Mobile" 3790 msgstr "Mobile" 3791 3792 msgid "Tablet" 3793 msgstr "Tablette" 3794 3795 msgid "Click Heatmap" 3796 msgstr "Carte Clics" 3797 3798 msgid "Move Heatmap" 3799 msgstr "Carte Mouvements" 3800 3801 msgid "Scroll Heatmap" 3802 msgstr "Carte Défilement" 3803 3804 msgid "Views:" 3805 msgstr "Vues :" 3806 3807 msgid "Clicks:" 3808 msgstr "Clics :" 3809 3810 msgid "Avg Time:" 3811 msgstr "Temps moyen :" 3812 3813 msgid "No heatmap data available for this page and device combination." 3814 msgstr "Aucune donnée pour cette page/appareil." 3815 3816 msgid "Top Clicked Elements" 3817 msgstr "Éléments Plus Cliqués" 3818 3819 msgid "Simple" 3820 msgstr "Simple" 3821 3822 msgid "Detailed" 3823 msgstr "Détaillé" 3824 3825 msgid "No heatmap data available" 3826 msgstr "Aucune donnée disponible" 3827 3828 3829 #: includes/trait-opti-behavior-settings-views.php:698 3830 msgid "Language settings saved successfully. Reloading page to apply new language..." 3831 msgstr "Paramètres de Langue Enregistrés avec Succès. Rechargement pour Appliquer la Nouvelle Langue..." -
opti-behavior/trunk/readme.txt
r3406294 r3408429 5 5 6 6 Requires at least: 5.8 7 Tested up to: 6. 97 Tested up to: 6.8 8 8 Requires PHP: 7.4 9 Stable tag: 1.0. 69 Stable tag: 1.0.7 10 10 License: GPLv2 or later 11 11 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 246 246 247 247 == Changelog == 248 249 = 1.0.7 - 2025-12-02 = 250 * Enhancement: Added French language translations for improved internationalization 251 * Fix: Resolved sendPageView function issues for accurate page tracking 252 * Fix: Corrected Returning Visitors calculation and display 253 * Fix: Fixed Logged In Visitors detection and counting 254 * Feature: Display username for logged-in visitors in Top Engaged Users widget 255 * Enhancement: Extended device type support for all device categories (desktop, mobile, tablet, PC) 256 * Code Quality: WordPress coding standards compliance improvements 257 * Code Quality: Added debug logging controls via settings page 258 * Security: Fixed nonce verification warnings 259 * Security: Enhanced prepared SQL statements with proper phpcs annotations 248 260 249 261 = 1.0.6 - 2025-11-30 = … … 317 329 == Upgrade Notice == 318 330 331 = 1.0.7 = 332 Important update with French translations, visitor tracking improvements, and username display in Top Engaged Users. Enhanced coding standards compliance and debug logging controls. 333 319 334 = 1.0.5 = 320 335 WordPress.org submission update: Fixes debug code, timezone handling, and i18n compliance. All users should update for WordPress coding standards compliance. -
opti-behavior/trunk/views/dashboard-views.php
r3399182 r3408429 72 72 <div class="dashboard-header"> 73 73 <div class="dashboard-title-section"> 74 <h1 class="dashboard-title"> 📊 Analytics Dashboard</h1>74 <h1 class="dashboard-title"><?php echo esc_html__( '📊 Analytics Dashboard', 'opti-behavior' ); ?></h1> 75 75 <div class="dashboard-subtitle"> 76 <span class="subtitle-text"> Real-time insights and user behavior analytics</span>76 <span class="subtitle-text"><?php echo esc_html__( 'Real-time insights and user behavior analytics', 'opti-behavior' ); ?></span> 77 77 </div> 78 78 </div> 79 79 <div class="dashboard-controls"> 80 80 <select class="period-selector" id="dashboard-period"> 81 <option value="today" <?php selected( $period, 'today' ); ?>> Today</option>82 <option value="yesterday" <?php selected( $period, 'yesterday' ); ?>> Yesterday</option>83 <option value="last7days" <?php selected( $period, 'last7days' ); ?>> Last 7 Days</option>84 <option value="last30days" <?php selected( $period, 'last30days' ); ?>> Last 30 Days</option>85 <option value="thismonth" <?php selected( $period, 'thismonth' ); ?>> This Month</option>86 <option value="custom" <?php selected( $period, 'custom' ); ?>> Custom Range</option>81 <option value="today" <?php selected( $period, 'today' ); ?>><?php echo esc_html__( 'Today', 'opti-behavior' ); ?></option> 82 <option value="yesterday" <?php selected( $period, 'yesterday' ); ?>><?php echo esc_html__( 'Yesterday', 'opti-behavior' ); ?></option> 83 <option value="last7days" <?php selected( $period, 'last7days' ); ?>><?php echo esc_html__( 'Last 7 Days', 'opti-behavior' ); ?></option> 84 <option value="last30days" <?php selected( $period, 'last30days' ); ?>><?php echo esc_html__( 'Last 30 Days', 'opti-behavior' ); ?></option> 85 <option value="thismonth" <?php selected( $period, 'thismonth' ); ?>><?php echo esc_html__( 'This Month', 'opti-behavior' ); ?></option> 86 <option value="custom" <?php selected( $period, 'custom' ); ?>><?php echo esc_html__( 'Custom Range', 'opti-behavior' ); ?></option> 87 87 </select> 88 88 <input type="date" id="start-date" value="<?php echo esc_attr( $start_val ); ?>" /> … … 90 90 <button class="refresh-btn" id="apply-range"> 91 91 <span class="refresh-icon">📅</span> 92 Apply92 <?php echo esc_html__( 'Apply', 'opti-behavior' ); ?> 93 93 </button> 94 94 <button class="refresh-btn" id="refresh-dashboard"> 95 95 <span class="refresh-icon">🔄</span> 96 Refresh96 <?php echo esc_html__( 'Refresh', 'opti-behavior' ); ?> 97 97 </button> 98 98 </div> … … 114 114 $fmt = function ( $delta ) { 115 115 $sign = ( $delta > 0 ? '+' : ( $delta < 0 ? '' : '' ) ); 116 return $sign . (int) round( $delta ) . '% vs last period'; 116 /* translators: %s: percentage change value with sign */ 117 return sprintf( esc_html__( '%s%% vs last period', 'opti-behavior' ), $sign . (int) round( $delta ) ); 117 118 }; 118 119 $cls = function ( $delta ) { … … 125 126 <div class="stat-content"> 126 127 <div class="stat-value"><?php echo esc_html( $stats['visitors'] ); ?></div> 127 <div class="stat-label"> Visitors</div>128 <div class="stat-label"><?php echo esc_html__( 'Visitors', 'opti-behavior' ); ?></div> 128 129 <div class="stat-change <?php echo esc_attr( $cls( $changes['visitors'] ?? 0 ) ); ?>"><?php echo esc_html( $fmt( $changes['visitors'] ?? 0 ) ); ?></div> 129 130 </div> … … 133 134 <div class="stat-content"> 134 135 <div class="stat-value"><?php echo esc_html( $stats['sessions'] ); ?></div> 135 <div class="stat-label"> Sessions</div>136 <div class="stat-label"><?php echo esc_html__( 'Sessions', 'opti-behavior' ); ?></div> 136 137 <div class="stat-change <?php echo esc_attr( $cls( $changes['sessions'] ?? 0 ) ); ?>"><?php echo esc_html( $fmt( $changes['sessions'] ?? 0 ) ); ?></div> 137 138 </div> … … 141 142 <div class="stat-content"> 142 143 <div class="stat-value"><?php echo esc_html( $stats['pageviews'] ); ?></div> 143 <div class="stat-label"> Page Views</div>144 <div class="stat-label"><?php echo esc_html__( 'Page Views', 'opti-behavior' ); ?></div> 144 145 <div class="stat-change <?php echo esc_attr( $cls( $changes['pageviews'] ?? 0 ) ); ?>"><?php echo esc_html( $fmt( $changes['pageviews'] ?? 0 ) ); ?></div> 145 146 </div> … … 154 155 ?> 155 156 </div> 156 <div class="stat-label"> Avg. Session Time</div>157 <div class="stat-label"><?php echo esc_html__( 'Avg. Session Time', 'opti-behavior' ); ?></div> 157 158 <div class="stat-change <?php echo esc_attr( $cls( $changes['avg_session_time'] ?? 0 ) ); ?>"><?php echo esc_html( $fmt( $changes['avg_session_time'] ?? 0 ) ); ?></div> 158 159 </div> … … 162 163 <div class="stat-content"> 163 164 <div class="stat-value"><?php echo esc_html( $stats['avg_scroll_depth'] ); ?>%</div> 164 <div class="stat-label"> Avg. Scroll Depth</div>165 <div class="stat-label"><?php echo esc_html__( 'Avg. Scroll Depth', 'opti-behavior' ); ?></div> 165 166 <div class="stat-change <?php echo esc_attr( $cls( $changes['avg_scroll_depth'] ?? 0 ) ); ?>"><?php echo esc_html( $fmt( $changes['avg_scroll_depth'] ?? 0 ) ); ?></div> 166 167 </div> … … 170 171 <div class="stat-content"> 171 172 <div class="stat-value"><?php echo esc_html( $stats['bounce_rate'] ); ?>%</div> 172 <div class="stat-label"> Bounce Rate</div>173 <div class="stat-label"><?php echo esc_html__( 'Bounce Rate', 'opti-behavior' ); ?></div> 173 174 <div class="stat-change <?php echo esc_attr( $cls( $changes['bounce_rate'] ?? 0 ) ); ?>"><?php echo esc_html( $fmt( $changes['bounce_rate'] ?? 0 ) ); ?></div> 174 175 </div> … … 196 197 <h3 class="widget-title"> 197 198 <span class="widget-icon">📈</span> 198 Traffic Overview199 <?php echo esc_html__( 'Traffic Overview', 'opti-behavior' ); ?> 199 200 </h3> 200 201 </div> … … 207 208 <?php opti_behavior_render_widget_loading(); ?> 208 209 <div class="widget-header"> 209 <h3 class="widget-title"><span class="widget-icon">🧭</span> Browsers</h3>210 <h3 class="widget-title"><span class="widget-icon">🧭</span> <?php echo esc_html__( 'Browsers', 'opti-behavior' ); ?></h3> 210 211 </div> 211 212 <div class="widget-content compact"> … … 217 218 <?php opti_behavior_render_widget_loading(); ?> 218 219 <div class="widget-header"> 219 <h3 class="widget-title"><span class="widget-icon">📱</span> Device Types</h3>220 <h3 class="widget-title"><span class="widget-icon">📱</span> <?php echo esc_html__( 'Device Types', 'opti-behavior' ); ?></h3> 220 221 </div> 221 222 <div class="widget-content compact"> … … 227 228 <?php opti_behavior_render_widget_loading(); ?> 228 229 <div class="widget-header"> 229 <h3 class="widget-title"><span class="widget-icon">💻</span> Operating Systems</h3>230 <h3 class="widget-title"><span class="widget-icon">💻</span> <?php echo esc_html__( 'Operating Systems', 'opti-behavior' ); ?></h3> 230 231 </div> 231 232 <div class="widget-content compact"> … … 239 240 <h3 class="widget-title"> 240 241 <span class="widget-icon">🎯</span> 241 User Intent242 <?php echo esc_html__( 'User Intent', 'opti-behavior' ); ?> 242 243 </h3> 243 244 </div> … … 262 263 <th>#</th> 263 264 <th><?php echo esc_html__( 'Visitor', 'opti-behavior' ); ?></th> 264 <th title="Average sessions per active day"> Daily Freq</th>265 <th title="Average time per session"> Avg Session</th>265 <th title="Average sessions per active day"><?php echo esc_html__( 'Daily Freq', 'opti-behavior' ); ?></th> 266 <th title="Average time per session"><?php echo esc_html__( 'Avg Session', 'opti-behavior' ); ?></th> 266 267 <th><?php echo esc_html__( 'Total Time', 'opti-behavior' ); ?></th> 267 268 <th><?php echo esc_html__( 'Sessions', 'opti-behavior' ); ?></th> 268 <th title="Pages per session"> Pages/Sess</th>269 <th title="Pages per session"><?php echo esc_html__( 'Pages/Sess', 'opti-behavior' ); ?></th> 269 270 <th><?php echo esc_html__( 'Country', 'opti-behavior' ); ?></th> 270 271 <th><?php echo esc_html__( 'Last Seen', 'opti-behavior' ); ?></th> … … 287 288 <?php opti_behavior_render_widget_loading(); ?> 288 289 <div class="widget-header"> 289 <h3 class="widget-title"><span class="widget-icon">🌍</span> Top Countries</h3>290 <h3 class="widget-title"><span class="widget-icon">🌍</span> <?php echo esc_html__( 'Top Countries', 'opti-behavior' ); ?></h3> 290 291 </div> 291 292 <div class="widget-content compact"> … … 298 299 <div class="widget-header"> 299 300 <h3 class="widget-title"> 300 <span class="live-badge" aria-label="Live"><span class="live-dot" aria-hidden="true"></span> Live</span>301 Real-time Visitors301 <span class="live-badge" aria-label="Live"><span class="live-dot" aria-hidden="true"></span><?php echo esc_html__( 'Live', 'opti-behavior' ); ?></span> 302 <?php echo esc_html__( 'Real-time Visitors', 'opti-behavior' ); ?> 302 303 <span class="visitor-count"><?php echo count( $dashboard_data['realtime']['active_visitors'] ); ?></span> 303 304 </h3> … … 315 316 $ip_raw = trim( $ip_raw ); 316 317 if ( '' === $ip_raw ) { 317 echo '-';318 echo esc_html__( '—', 'opti-behavior' ); 318 319 } elseif ( false !== strpos( $ip_raw, ':' ) ) { 319 320 $start = substr( $ip_raw, 0, 7 ); … … 331 332 <div class="optibehavior-empty-state is-visible"> 332 333 <svg viewBox='0 0 24 24' fill='none' stroke='#9ca3af' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M16 11a4 4 0 1 0-8 0'/><path d='M3 21a7 7 0 0 1 18 0'/></svg> 333 <div class="optibehavior-empty-title"> No active visitors right now</div>334 <div class="optibehavior-empty-sub"> Traffic updates in real-time.</div>334 <div class="optibehavior-empty-title"><?php echo esc_html__( 'No active visitors right now', 'opti-behavior' ); ?></div> 335 <div class="optibehavior-empty-sub"><?php echo esc_html__( 'Traffic updates in real-time.', 'opti-behavior' ); ?></div> 335 336 </div> 336 337 <?php endif; ?> … … 341 342 <div class="dashboard-widget realtime-map-widget"> 342 343 <div class="widget-header"> 343 <h3 class="widget-title"><span class="widget-icon">🗺️</span> Real-time Visitor Map</h3>344 <h3 class="widget-title"><span class="widget-icon">🗺️</span> <?php echo esc_html__( 'Real-time Visitor Map', 'opti-behavior' ); ?></h3> 344 345 </div> 345 346 <div class="widget-content"> … … 356 357 <svg class="widget-icon-svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#4f46e5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><path d="M14 2v6h6"></path></svg> 357 358 </span> 358 Top Pages359 <?php echo esc_html__( 'Top Pages', 'opti-behavior' ); ?> 359 360 </h3> 360 361 </div> … … 364 365 <div class="optibehavior-empty-state is-visible"> 365 366 <svg viewBox='0 0 24 24' fill='none' stroke='#9ca3af' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 3h14a2 2 0 0 1 2 2v14l-4-4H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z'/></svg> 366 <div class="optibehavior-empty-title"> No page views yet</div>367 <div class="optibehavior-empty-sub"> Once visitors view pages, you’ll see them here.</div>367 <div class="optibehavior-empty-title"><?php echo esc_html__( 'No page views yet', 'opti-behavior' ); ?></div> 368 <div class="optibehavior-empty-sub"><?php echo esc_html__( 'Once visitors view pages, you\'ll see them here.', 'opti-behavior' ); ?></div> 368 369 </div> 369 370 <?php else : ?> … … 403 404 <a class="optibehavior-heatmap-btn" target="_blank" href="<?php echo esc_url( $page['pc_heatmap'] ); ?>" aria-label="Open PC heatmap for <?php echo esc_attr( $page_title ); ?>"> 404 405 <span class="optibehavior-heatmap-icon" aria-hidden="true">🖥️</span> 405 <span class="optibehavior-heatmap-label"> PC</span>406 <span class="optibehavior-heatmap-label"><?php echo esc_html__( 'PC', 'opti-behavior' ); ?></span> 406 407 </a> 407 408 <a class="optibehavior-heatmap-btn alt" target="_blank" href="<?php echo esc_url( $page['mobile_heatmap'] ); ?>" aria-label="Open Mobile heatmap for <?php echo esc_attr( $page_title ); ?>"> 408 409 <span class="optibehavior-heatmap-icon" aria-hidden="true">📱</span> 409 <span class="optibehavior-heatmap-label"> Mobile</span>410 <span class="optibehavior-heatmap-label"><?php echo esc_html__( 'Mobile', 'opti-behavior' ); ?></span> 410 411 </a> 411 412 </div> … … 444 445 <?php opti_behavior_render_widget_loading(); ?> 445 446 <div class="widget-header"> 446 <h3 class="widget-title"><span class="widget-icon">🔗</span> Top Referrers</h3>447 <h3 class="widget-title"><span class="widget-icon">🔗</span> <?php echo esc_html__( 'Top Referrers', 'opti-behavior' ); ?></h3> 447 448 </div> 448 449 <div class="widget-content compact"> -
opti-behavior/trunk/views/heatmaps-views.php
r3399182 r3408429 41 41 ?> 42 42 <div class="heatmaps-header"> 43 <h1 class="heatmaps-title"> 🔥 Heatmaps</h1>43 <h1 class="heatmaps-title"><?php esc_html_e( '🔥 Heatmaps', 'opti-behavior' ); ?></h1> 44 44 <div class="heatmaps-controls"> 45 45 <select id="heatmaps-preset"> … … 49 49 <option value="top-engagement" <?php selected( $preset, 'top-engagement' ); ?>>Top Engagement</option> 50 50 </select> 51 <button id="refresh-heatmaps" class="button"> Refresh</button>51 <button id="refresh-heatmaps" class="button"><?php esc_html_e( 'Refresh', 'opti-behavior' ); ?></button> 52 52 </div> 53 53 </div>
Note: See TracChangeset
for help on using the changeset viewer.