Plugin Directory

Changeset 3445725


Ignore:
Timestamp:
01/23/2026 04:49:32 PM (4 weeks ago)
Author:
2wstechnologies
Message:

fix the insights display in visitors journey page + clean all the console logs

Location:
convertybot
Files:
97 added
24 edited

Legend:

Unmodified
Added
Removed
  • convertybot/trunk/assets/js/admin-analytics-dashboard.js

    r3437100 r3445725  
    3131        this.initializeCharts();
    3232        this.updateLastUpdateTime();
    33 
    34         // DEBUG: Log all dashboard data for charts
    35         console.log('═══════════════════════════════════════════════════════════');
    36         console.log('📊 Enhanced Analytics Dashboard initialized');
    37         console.log('═══════════════════════════════════════════════════════════');
    38         console.log('📊 [FULL DATA] All dashboard data received from backend:', this.config.dashboardData);
    39         console.log('📊 [Session Stats]:', this.config.dashboardData?.session_stats);
    40         console.log('📊 [Comparison Data]:', this.config.dashboardData?.comparison_data);
    41         console.log('📊 [Hourly Pattern] Records:', this.config.dashboardData?.hourly_pattern?.length || 0);
    42         console.log('📊 [Hourly Pattern] Sample:', this.config.dashboardData?.hourly_pattern?.slice(0, 3));
    43         console.log('📊 [Conversion Funnel]:', this.config.dashboardData?.conversion_funnel);
    44         console.log('📊 [Device Breakdown]:', this.config.dashboardData?.device_breakdown);
    45         console.log('📊 [Top Products] Count:', this.config.dashboardData?.top_products?.length || 0);
    46         console.log('═══════════════════════════════════════════════════════════');
    4733    }
    4834
     
    139125    initializeCharts() {
    140126        if (typeof Chart === 'undefined') {
    141             console.warn('Chart.js not loaded');
    142127            return;
    143128        }
     
    159144            this.initHeatmapChart();
    160145            this.initMiniTrendCharts();
    161             console.log('Charts initialized successfully');
    162146        } catch (error) {
    163147            console.error('Error initializing charts:', error);
     
    174158                    delete this.charts[key];
    175159                } catch (error) {
    176                     console.warn(`Failed to destroy chart ${key}:`, error);
     160                    // Chart destruction failed - continue anyway
    177161                }
    178162            }
     
    271255        // Get real data from backend
    272256        const hourlyMetrics = this.config.dashboardData.hourly_pattern || [];
    273 
    274         // DEBUG: Log raw data from backend
    275         console.log('📊 [Revenue Chart] Raw hourly_pattern data:', {
    276             totalRecords: hourlyMetrics.length,
    277             sampleData: hourlyMetrics.slice(0, 5),
    278             allData: hourlyMetrics,
    279             currentTimeframe: this.currentTimeframe
    280         });
    281257
    282258        // Aggregate data based on current timeframe
     
    318294        });
    319295
    320         // DEBUG: Log aggregated data with actual values
    321         console.log('📊 [Revenue Chart] Aggregated data:', {
    322             timeframe: this.currentTimeframe,
    323             labels: labels,
    324             revenueDataValues: JSON.stringify(revenueData),
    325             conversionDataValues: JSON.stringify(conversionData),
    326             aggregatedRecords: aggregatedData.length,
    327             totalRevenue: revenueData.reduce((a, b) => a + b, 0),
    328             totalSessions: aggregatedData.reduce((a, b) => a + (b.sessions || 0), 0),
    329             rawAggregated: JSON.stringify(aggregatedData)
    330         });
    331 
    332296        // Destroy existing revenue chart if exists
    333297        if (this.charts.revenue) {
    334             console.log('📊 [Revenue Chart] Destroying existing chart');
    335298            this.charts.revenue.destroy();
    336299            this.charts.revenue = null;
     
    338301
    339302        setTimeout(() => {
    340             console.log('📊 [Revenue Chart] Creating new chart with', revenueData.length, 'data points');
    341 
    342303            // Get sessions data - this is now the default
    343304            const sessionsData = aggregatedData.map(d => d.sessions || 0);
    344             const hasRevenue = revenueData.some(v => v > 0);
    345             const hasSessions = sessionsData.some(v => v > 0);
    346 
    347             console.log('📊 [Revenue Chart] Data check:', {
    348                 hasRevenue,
    349                 hasSessions,
    350                 revenueSum: revenueData.reduce((a, b) => a + b, 0),
    351                 sessionsSum: sessionsData.reduce((a, b) => a + b, 0)
    352             });
    353305
    354306            // Use sessions data as primary (default selection)
     
    475427        const canvas = document.getElementById('funnelChart');
    476428        if (!canvas) {
    477             console.warn('Funnel chart canvas not found');
    478429            return;
    479430        }
     
    482433            // Get real conversion funnel data from backend
    483434            const funnel = this.config.dashboardData.conversion_funnel || {};
    484 
    485             // DEBUG: Log funnel data
    486             console.log('📊 [Funnel Chart] Raw conversion_funnel data:', {
    487                 rawFunnel: funnel,
    488                 sessions: funnel.sessions,
    489                 chat_initiated: funnel.chat_initiated,
    490                 products_viewed: funnel.products_viewed,
    491                 add_to_cart: funnel.add_to_cart,
    492                 purchases: funnel.purchases
    493             });
    494435
    495436            const data = {
     
    503444                ]
    504445            };
    505 
    506             console.log('📊 [Funnel Chart] Processed values:', data.values);
    507446
    508447            this.charts.funnel = new Chart(canvas, {
     
    558497        const canvas = document.getElementById('aiAccuracyGauge');
    559498        if (!canvas) {
    560             console.warn('AI Gauge chart canvas not found');
    561499            return;
    562500        }
     
    600538        const canvas = document.getElementById('deviceChart');
    601539        if (!canvas) {
    602             console.warn('Device chart canvas not found');
    603540            return;
    604541        }
     
    651588        const canvas = document.getElementById('activityHeatmap');
    652589        if (!canvas) {
    653             console.warn('Heatmap chart canvas not found');
    654590            return;
    655591        }
     
    660596            const hours = Array.from({ length: 24 }, (_, i) => `${i}:00`);
    661597            const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    662 
    663             // DEBUG: Log heatmap data
    664             console.log('📊 [Heatmap Chart] Raw hourly_pattern data:', {
    665                 totalRecords: hourlyMetrics.length,
    666                 sampleData: hourlyMetrics.slice(0, 10),
    667                 hasHourField: hourlyMetrics.length > 0 ? hourlyMetrics[0].hour !== undefined : false,
    668                 hasDayField: hourlyMetrics.length > 0 ? hourlyMetrics[0].day !== undefined : false
    669             });
    670598
    671599            // Group hourly metrics by day of week and hour
     
    818746            }
    819747        }, 4000);
    820 
    821         console.log(`${type.toUpperCase()}: ${message}`);
    822748    }
    823749
     
    844770        this.loadDashboardData().then(() => {
    845771            this.showNotification('Dashboard refreshed successfully', 'success');
    846         }).catch((error) => {
    847             console.error('Failed to refresh dashboard:', error);
     772        }).catch(() => {
    848773            this.showNotification('Refreshing page...', 'info');
    849774            // Fallback to page reload if AJAX fails
     
    876801            }
    877802        } catch (error) {
    878             console.warn('API request failed, using fallback data:', error);
    879803            // Use mock data as fallback
    880804            this.updateLastUpdateTime();
     
    909833            return result;
    910834        } catch (error) {
    911             console.error(`API request failed for ${action}:`, error);
    912835            throw error;
    913836        }
     
    1042965
    1043966    updateChartTimeframe(timeframe) {
    1044         console.log('📊 [Timeframe Change] Switching from', this.currentTimeframe, 'to', timeframe);
    1045 
    1046967        // Update active button
    1047968        document.querySelectorAll('.chart-control').forEach(btn => {
     
    1053974
    1054975        // Reinitialize charts with new timeframe
    1055         console.log('📊 [Timeframe Change] Reinitializing charts...');
    1056976        this.initializeCharts();
    1057977
     
    1060980
    1061981    updateRevenueChart(metric) {
    1062         console.log('📊 [Revenue Chart] Switching metric to:', metric);
    1063 
    1064982        // Update the revenue chart to show different metrics
    1065983        if (!this.charts.revenue) {
    1066             console.warn('Revenue chart not initialized');
    1067984            return;
    1068985        }
     
    11101027        }
    11111028
    1112         console.log('📊 [Revenue Chart] New data for', metric, ':', {
    1113             dataLength: newData.length,
    1114             values: JSON.stringify(newData),
    1115             sum: newData.reduce((a, b) => a + b, 0)
    1116         });
    1117 
    11181029        // Update the first dataset (revenue/main metric)
    11191030        this.charts.revenue.data.datasets[0].data = newData.length > 0 ? newData : [0];
     
    11241035
    11251036        this.charts.revenue.update('active');
    1126         console.log('📊 [Revenue Chart] Updated to show:', label);
    11271037    }
    11281038
     
    11391049                delete this.charts.heatmap;
    11401050            } catch (error) {
    1141                 console.warn('Failed to destroy heatmap chart:', error);
     1051                // Heatmap chart destruction failed - continue anyway
    11421052            }
    11431053        }
     
    15681478    toggleFullscreen() {
    15691479        if (!document.fullscreenElement) {
    1570             document.documentElement.requestFullscreen?.().catch(err => {
    1571                 console.error('Error attempting to enable fullscreen:', err);
     1480            document.documentElement.requestFullscreen?.().catch(() => {
    15721481                this.showNotification('Fullscreen not supported', 'warning');
    15731482            });
  • convertybot/trunk/assets/js/admin-conversations.js

    r3437100 r3445725  
    3131        // Initialize the conversation viewer
    3232        init: function() {
    33             console.log('ConvertyBot Conversations starting initialization...');
    34            
    3533            // Merge configuration from template
    3634            if (window.convertyBotConversationsConfig) {
    37                 console.log('Merging configuration from template:', window.convertyBotConversationsConfig);
    3835                // Merge the config object with template config
    3936                Object.assign(this, window.convertyBotConversationsConfig);
    4037            }
    41            
    42             console.log('Final configuration:', this);
    43            
     38
    4439            // Verify required properties
    4540            if (!this.ajaxurl || !this.nonce) {
     
    4843                return;
    4944            }
    50            
     45
    5146            this.compileTemplates();
    5247            this.bindEvents();
     
    5449            this.initRealTime();
    5550            this.setupAutoRefresh();
    56            
    57             console.log('ConvertyBot Conversations initialized');
    5851        },
    5952       
     
    135128            // Debug helper to log data
    136129            Handlebars.registerHelper('debug', function(data) {
    137                 console.log('Handlebars debug:', data);
     130                // Debug logging removed for production
    138131                return '';
    139132            });
     
    354347                e.preventDefault();
    355348                var page = parseInt($(this).data('page'));
    356                 console.log('📄 Pagination click:', {
    357                     clickedPage: page,
    358                     currentPage: self.config.currentPage,
    359                     element: $(this).text()
    360                 });
    361349                if (page && page !== self.config.currentPage) {
    362                     console.log('📄 Loading page:', page);
    363350                    self.config.currentPage = page;
    364351                    self.loadConversations();
    365                 } else {
    366                     console.log('📄 Same page or invalid, not loading');
    367352                }
    368353            });
     
    372357        loadConversations: function() {
    373358            var self = this;
    374            
    375             console.log('loadConversations called');
    376             console.log('Configuration check:', {
    377                 hasConfig: !!convertyBotConversations,
    378                 hasAjaxUrl: !!(convertyBotConversations && convertyBotConversations.ajaxurl),
    379                 hasNonce: !!(convertyBotConversations && convertyBotConversations.nonce),
    380                 config: convertyBotConversations,
    381                 windowVars: Object.keys(window).filter(key => key.includes('ConvertyBot') || key.includes('convertyBot'))
    382             });
    383            
     359
    384360            // Check if essential configuration is available
    385361            if (!convertyBotConversations || !convertyBotConversations.ajaxurl || !convertyBotConversations.nonce) {
    386                 console.error('Configuration missing!', convertyBotConversations);
    387                 console.error('Available window variables:', Object.keys(window).filter(key => key.toLowerCase().includes('convertybot')));
     362                console.error('Configuration missing - ajaxurl or nonce not available');
    388363                self.showError('Configuration error: Missing required AJAX settings. Please check WordPress localization in admin.php');
    389364                return;
     
    410385                sort: this.config.filters.sort
    411386            };
    412            
    413             console.log('Making AJAX request with data:', data);
    414            
     387
    415388            $.post(convertyBotConversations.ajaxurl, data)
    416389                .done(function(response) {
    417                     console.log('🔍 AJAX response:', response);
    418                     console.log('🔍 Response keys:', Object.keys(response));
    419390                    $('#conversationsList .loading-spinner').hide();
    420                    
     391
    421392                    if (response.success) {
    422393                        var dataToRender = response.data || response;
    423                         console.log('🔍 Passing to renderConversations:', dataToRender);
    424394                        self.renderConversations(dataToRender);
    425395                       
     
    433403                })
    434404                .fail(function(xhr, status, error) {
    435                     console.error('AJAX request failed:', {
    436                         status: status,
    437                         error: error,
    438                         responseText: xhr.responseText,
    439                         xhr: xhr
    440                     });
    441405                    $('#conversationsList .loading-spinner').hide();
    442406                    self.showError('AJAX Error: ' + error + ' (Status: ' + status + ')');
     
    449413            var container = $('#conversationsList');
    450414            container.empty();
    451            
    452             console.log('🔍 renderConversations data:', data);
    453             console.log('🔍 Data keys:', data ? Object.keys(data) : 'N/A');
    454            
     415
    455416            var conversations = [];
    456417            if (data && data.conversations) {
    457418                conversations = data.conversations;
    458                 console.log('✅ Found conversations in data.conversations');
    459419            } else if (data && data.data && data.data.conversations) {
    460420                conversations = data.data.conversations;
    461                 console.log('✅ Found conversations in data.data.conversations');
    462421            } else if (Array.isArray(data)) {
    463422                conversations = data;
    464                 console.log('✅ Data is directly an array');
    465             } else {
    466                 console.log('❌ No conversations found');
    467                 console.log('🔍 Full data:', JSON.stringify(data, null, 2));
    468             }
    469            
    470             console.log('📊 Conversations count:', conversations.length);
    471             console.log('📊 Is array:', Array.isArray(conversations));
     423            }
    472424           
    473425            if (!Array.isArray(conversations) || conversations.length === 0) {
     
    477429           
    478430            conversations.forEach(function(conversation, index) {
    479                 console.log('🔍 Conversation', index + 1, ':', conversation);
    480                 console.log('📋 Keys:', Object.keys(conversation));
    481                 console.log('📋 Metadata:', conversation.metadata);
    482                 console.log('📋 Tags:', conversation.tags);
    483                 console.log('📋 Notes:', conversation.adminNotes);
    484                
    485431                var tags = [];
    486432                var notes = [];
    487                
     433
    488434                if (conversation.metadata?.tags) {
    489435                    tags = conversation.metadata.tags;
    490                     console.log('✅ Tags from metadata:', tags);
    491436                }
    492437                if (conversation.metadata?.adminNotes) {
    493438                    notes = conversation.metadata.adminNotes;
    494                     console.log('✅ Notes from metadata:', notes);
    495439                }
    496440                if (conversation.tags && tags.length === 0) {
    497441                    tags = conversation.tags;
    498                     console.log('✅ Tags from root:', tags);
    499442                }
    500443                if (conversation.adminNotes && notes.length === 0) {
    501444                    notes = conversation.adminNotes;
    502                     console.log('✅ Notes from root:', notes);
    503                 }
    504                
    505                 console.log('🏷️ Final tags:', tags);
    506                 console.log('📝 Final notes:', notes);
     445                }
    507446
    508447                // CRITICAL FIX: Use pre-computed values from PHP if available, fallback to JS calculation
     
    524463                var statusLabel = conversation.statusLabel || self.getStatusLabel(status);
    525464
    526                 // Debug: Log what we received from PHP
    527                 console.log('🔍 PHP pre-computed values:', {
    528                     phpTimeAgo: conversation.timeAgo,
    529                     phpStatus: conversation.status,
    530                     phpStatusLabel: conversation.statusLabel,
    531                     finalTimeAgo: timeAgo,
    532                     finalStatus: status,
    533                     finalStatusLabel: statusLabel
    534                 });
    535 
    536465                // ✅ FIX: Extract user info - check ALL possible paths for name AND email
    537466                var userName = conversation.userName || conversation.userInfo?.userName || conversation.user?.name || conversation.user?.userName || null;
     
    539468                var userEmail = conversation.userEmail || conversation.userInfo?.userEmail || conversation.userInfo?.email || conversation.user?.email || conversation.email || null;
    540469                var userId = conversation.userId || null;
    541 
    542                 // 🔍 DEBUG: Log extraction
    543                 console.log('🔍 List User Info:', { userName, userEmail, userId, raw: conversation });
    544470
    545471                // Build display name: prefer actual name, fallback to email, then userId, then Anonymous
     
    582508                };
    583509
    584                 console.log('🎨 Final template data:', templateData);
    585 
    586510                try {
    587511                    var html;
    588512                    if (self.templates.conversation) {
    589                         console.log('📝 Using Handlebars template');
    590513                        html = self.templates.conversation(templateData);
    591514                    } else {
    592                         console.log('📝 Using fallback generateConversationHTML');
    593515                        html = self.generateConversationHTML(templateData);
    594516                    }
    595                     console.log('📄 Generated HTML preview:', html.substring(0, 500));
    596517                    container.append(html);
    597                     console.log('✅ Conversation rendered');
    598518                } catch (error) {
    599                     console.error('❌ Render error:', error);
     519                    console.error('Render error for conversation:', error);
    600520                    container.append('<div class="conversation-error">Error rendering conversation</div>');
    601521                }
     
    626546                .done(function(response) {
    627547                    $('#conversationViewer .messages-loading').hide();
    628                    
    629                     console.log('🌐 Conversation loaded - Messages:', response.data && response.data.messages ? response.data.messages.length : 0);
    630                    
     548
    631549                    if (response.success) {
    632550                        self.renderConversationDetails(response.data);
    633551                    } else {
    634                         console.error('❌ AJAX Response failed:', response);
    635552                        self.showError((response && response.data && response.data.error) || (convertyBotConversations.strings && convertyBotConversations.strings.error) || 'An error occurred loading conversation');
    636553                    }
     
    645562        renderConversationDetails: function(data) {
    646563            var self = this;
    647             console.log('🔍 renderConversationDetails data:', data);
    648            
     564
    649565            var sessionData = data.session || data;
    650             console.log('📋 Session data:', sessionData);
    651             console.log('📋 Data keys:', Object.keys(data));
    652            
     566
    653567            var notes = [];
    654568            var tags = [];
    655            
     569
    656570            // Check all possible locations for tags and notes
    657             console.log('🔍 Checking for notes and tags in data structure...');
    658             console.log('🔍 data.adminNotes:', data.adminNotes);
    659             console.log('🔍 data.tags:', data.tags);
    660             console.log('🔍 data.metadata:', data.metadata);
    661             console.log('🔍 sessionData.metadata:', sessionData?.metadata);
    662            
    663571            if (data.adminNotes && Array.isArray(data.adminNotes)) {
    664572                notes = data.adminNotes;
    665                 console.log('✅ Notes from data.adminNotes:', notes);
    666             }
    667            
     573            }
     574
    668575            if (data.tags && Array.isArray(data.tags)) {
    669576                tags = data.tags;
    670                 console.log('✅ Tags from data.tags:', tags);
    671             }
    672            
     577            }
     578
    673579            if (data.metadata?.adminNotes && notes.length === 0) {
    674580                notes = data.metadata.adminNotes;
    675                 console.log('✅ Notes from data.metadata:', notes);
    676             }
    677            
     581            }
     582
    678583            if (data.metadata?.tags && tags.length === 0) {
    679584                tags = data.metadata.tags;
    680                 console.log('✅ Tags from data.metadata:', tags);
    681             }
    682            
     585            }
     586
    683587            if (sessionData?.metadata?.adminNotes && notes.length === 0) {
    684588                notes = sessionData.metadata.adminNotes;
    685                 console.log('✅ Notes from sessionData.metadata:', notes);
    686             }
    687            
     589            }
     590
    688591            if (sessionData?.metadata?.tags && tags.length === 0) {
    689592                tags = sessionData.metadata.tags;
    690                 console.log('✅ Tags from sessionData.metadata:', tags);
    691             }
    692            
    693             console.log('🏷️ Final tags:', tags);
    694             console.log('📝 Final notes:', notes);
     593            }
    695594           
    696595            // Render conversation info
     
    713612                wpUserId = String(sessionData.userInfo.wpUserId);
    714613            }
    715 
    716             // 🔍 DEBUG: Log all extracted values
    717             console.log('🔍 User Info Extraction:', {
    718                 firstName: firstName,
    719                 lastName: lastName,
    720                 userName: userName,
    721                 userEmail: userEmail,
    722                 userId: userId,
    723                 wpUserId: wpUserId,
    724                 isGuest: isGuest,
    725                 rawSessionData: sessionData,
    726                 rawData: data
    727             });
    728614
    729615            // ✅ FIX: Build display name with priority: firstName+lastName → userName → email
     
    790676            // ✅ NEW: Fetch WordPress user info if we have wpUserId but no displayName
    791677            if (shouldFetchUserInfo && wpUserId) {
    792                 console.log('🔄 Fetching WordPress user info for wpUserId:', wpUserId);
    793678                $.ajax({
    794679                    url: convertyBotConversations.ajax_url,
     
    799684                    },
    800685                    success: function(response) {
    801                         console.log('✅ WordPress user info response:', response);
    802686                        if (response.success && response.data) {
    803687                            var fetchedName = response.data.displayName || response.data.userName || response.data.userLogin;
    804                             var fetchedEmail = response.data.userEmail;
    805688                            if (fetchedName) {
    806689                                var $nameElement = $('#' + userNameElementId);
    807690                                $nameElement.html('<strong>👤 Name:</strong> ' + fetchedName);
    808                                 console.log('✅ Updated user name display to:', fetchedName);
    809691                            }
    810692                        }
    811693                    },
    812694                    error: function(xhr, status, error) {
    813                         console.log('⚠️ Failed to fetch WordPress user info:', error);
    814695                        // Keep showing "WordPress User #X" as fallback
    815696                        var $nameElement = $('#' + userNameElementId);
     
    821702            var messagesContainer = $('#messagesContainer');
    822703            messagesContainer.empty();
    823            
    824             console.log('🔍 Messages count:', data.messages ? data.messages.length : 0);
    825            
     704
    826705            if (data.messages && data.messages.length > 0) {
    827706                data.messages.sort(function(a, b) {
     
    869748                        messagesContainer.append(html);
    870749                    } catch (error) {
    871                         console.error('Message render error:', error);
     750                        console.error('Message render error:', error);
    872751                        messagesContainer.append('<div class="message-error">Error rendering message</div>');
    873752                    }
     
    882761        renderAdminNotes: function(notes, tags) {
    883762            var self = this;
    884             console.log('🔍 renderAdminNotes - Notes:', notes, 'Tags:', tags);
    885            
     763
    886764            var container = $('#notesContainer');
    887765            container.empty();
    888            
     766
    889767            if (tags && tags.length > 0) {
    890                 console.log('🏷️ Rendering tags:', tags);
    891768                var tagsHtml = '<div class="tags-section" style="background: #f0f8ff; padding: 15px; border-radius: 5px; margin: 10px 0; border-left: 4px solid #0066cc;">';
    892769                tagsHtml += '<h4 style="margin: 0 0 10px 0; color: #0066cc;">🏷️ Tags (' + tags.length + ')</h4>';
     
    900777           
    901778            if (notes && notes.length > 0) {
    902                 console.log('📝 Rendering notes:', notes);
    903779                var notesHtml = '<div class="notes-section" style="background: #f9f9f9; padding: 15px; border-radius: 5px; margin: 10px 0; border-left: 4px solid #0073aa;">';
    904780                notesHtml += '<h4 style="margin: 0 0 10px 0; color: #0073aa;">📝 Admin Notes (' + notes.length + ')</h4>';
    905781                notes.forEach(function(note, index) {
    906                     console.log('📝 Rendering note ' + (index + 1) + ':', note);
    907782                    notesHtml += '<div class="note-item" style="background: white; padding: 10px; margin: 8px 0; border-radius: 3px; border: 1px solid #ddd;">';
    908783                    notesHtml += '<div class="note-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px; font-size: 12px; color: #666;">';
     
    935810                container.append(notesHtml);
    936811            } else {
    937                 console.log('📝 No notes to display');
    938812                container.append('<div class="no-notes" style="text-align: center; padding: 20px; color: #666; background: #f9f9f9; border-radius: 5px;"><p>📝 No admin notes yet.</p></div>');
    939813            }
     
    978852                // Export all conversations from backend, not just visible ones
    979853                exportAll = true;
    980                 console.log('📤 Export All mode - will fetch all conversations from server');
    981854            }
    982855
     
    1008881            };
    1009882
    1010             console.log('📤 Export request data:', data);
    1011 
    1012883            $.post(convertyBotConversations.ajaxurl, data)
    1013884                .done(function(response) {
    1014                     console.log('📥 Export response:', response);
    1015                     console.log('📥 Export response.data:', response.data);
    1016                     console.log('📥 Export response.data.conversations:', response.data ? response.data.conversations : 'N/A');
    1017 
    1018885                    if (response.success && response.data) {
    1019886                        // Create download from the received data
     
    1021888                        var filename, content, mimeType;
    1022889
    1023                         console.log('📦 Export data object:', exportData);
    1024                         console.log('📦 Has conversations?', !!exportData.conversations);
    1025                         console.log('📦 Conversations count:', exportData.conversations ? exportData.conversations.length : 0);
    1026 
    1027890                        if (exportData.downloadUrl) {
    1028891                            // If backend provides a download URL, use it
    1029                             console.log('🔗 Using download URL:', exportData.downloadUrl);
    1030892                            window.open(exportData.downloadUrl, '_blank');
    1031893                        } else if (exportData.conversations && exportData.conversations.length > 0) {
     
    1033895                            var formatType = exportData.format || format;
    1034896                            var timestamp = new Date().toISOString().slice(0, 10);
    1035 
    1036                             console.log('📝 Creating file with format:', formatType);
    1037897
    1038898                            if (formatType === 'json') {
     
    1055915                            }
    1056916
    1057                             console.log('📁 File details:', { filename: filename, mimeType: mimeType, contentLength: content.length });
    1058 
    1059917                            // Trigger download
    1060918                            try {
     
    1066924                                link.style.display = 'none';
    1067925                                document.body.appendChild(link);
    1068                                 console.log('📥 Triggering download...');
    1069926                                link.click();
    1070927
     
    1073930                                    document.body.removeChild(link);
    1074931                                    URL.revokeObjectURL(url);
    1075                                     console.log('✅ Download triggered successfully');
    1076932                                }, 100);
    1077933                            } catch (downloadError) {
    1078                                 console.error('Download error:', downloadError);
     934                                console.error('Download error:', downloadError);
    1079935                                self.showError('Failed to create download: ' + downloadError.message);
    1080936                                return;
    1081937                            }
    1082938                        } else {
    1083                             console.warn('⚠️ No conversations in export data');
    1084939                            self.showError('No conversations data received from server');
    1085940                            return;
     
    1089944                        self.hideExportModal();
    1090945                    } else {
    1091                         console.error('❌ Export failed:', response);
    1092946                        self.showError((response && response.data) || (convertyBotConversations.strings && convertyBotConversations.strings.export_error) || 'Export failed');
    1093947                    }
    1094948                })
    1095949                .fail(function(xhr, status, error) {
    1096                     console.error('❌ Export AJAX failed:', status, error);
    1097950                    self.showError((convertyBotConversations.strings && convertyBotConversations.strings.export_error) || 'Export failed: ' + error);
    1098951                })
     
    12881141                })
    12891142                .fail(function() {
    1290                     console.warn('Failed to load current tags');
     1143                    // Failed to load current tags
    12911144                });
    12921145        },
     
    13261179                priority: priority
    13271180            };
    1328            
    1329             console.log('📤 Quick note data:', data);
     1181
    13301182            $('#saveQuickNote').prop('disabled', true).text('Saving...');
    13311183           
     
    14071259           
    14081260            $('#saveNote').prop('disabled', true).text('Saving...');
    1409            
    1410             console.log('📤 Sending note data:', data);
    1411             console.log('📤 AJAX URL:', convertyBotConversations.ajaxurl);
     1261
    14121262            $.post(convertyBotConversations.ajaxurl, data)
    14131263                .done(function(response) {
    1414                     console.log('💾 Note save response:', response);
    1415                     console.log('💾 Response type:', typeof response);
    14161264                    if (response.success) {
    14171265                        self.showSuccess((convertyBotConversations.strings && convertyBotConversations.strings.note_saved) || 'Note saved successfully');
    14181266                        self.hideAddNoteForm();
    1419                        
     1267
    14201268                        // Force reload conversation data
    1421                         console.log('🔄 Reloading conversation after note save...');
    14221269                        setTimeout(function() {
    14231270                            self.viewConversation(self.config.currentConversationId);
     
    14681315            $.post(convertyBotConversations.ajaxurl, data)
    14691316                .done(function(response) {
    1470                     console.log('🏷️ Tag save response:', response);
    14711317                    if (response.success) {
    14721318                        self.showSuccess('Tags saved successfully');
    14731319                        self.hideAddTagForm();
    1474                        
     1320
    14751321                        // Force reload conversation data
    1476                         console.log('🔄 Reloading conversation after tag save...');
    14771322                        setTimeout(function() {
    14781323                            self.viewConversation(self.config.currentConversationId);
     
    16481493            // Ensure status is a string
    16491494            if (typeof status !== 'string') {
    1650                 console.warn('getStatusLabel received non-string status:', status);
    16511495                status = 'active';
    16521496            }
     
    16631507
    16641508            var result = labels[status] || status.charAt(0).toUpperCase() + status.slice(1);
    1665             console.log('getStatusLabel:', status, '->', result);
    16661509            return result;
    16671510        },
     
    16981541
    16991542        formatTimeAgo: function(timestamp) {
    1700             console.log('formatTimeAgo input:', timestamp, 'type:', typeof timestamp);
    17011543            if (!timestamp) {
    1702                 console.warn('formatTimeAgo: timestamp is falsy, returning Just now');
    17031544                return 'Just now';
    17041545            }
     
    18781719        updatePagination: function(pagination) {
    18791720            if (!pagination) {
    1880                 console.log('⚠️ updatePagination: no pagination data');
    18811721                return;
    18821722            }
    1883 
    1884             console.log('📄 updatePagination called with:', pagination);
    18851723
    18861724            this.config.totalConversations = pagination.total;
     
    18901728                this.config.currentPage = pagination.currentPage;
    18911729            }
    1892 
    1893             console.log('📄 Updated config:', {
    1894                 currentPage: this.config.currentPage,
    1895                 totalPages: this.config.totalPages,
    1896                 totalConversations: this.config.totalConversations
    1897             });
    18981730
    18991731            var paginationHtml = '';
  • convertybot/trunk/assets/js/admin-coupons.js

    r3437100 r3445725  
    5555        const isActive = $(this).is(':checked');
    5656
    57         console.log('Toggle status - Rule ID:', ruleId, 'Is Active:', isActive);
    58 
    5957        $.ajax({
    6058            url: ajaxurl,
     
    6765            },
    6866            success: function(response) {
    69                 console.log('Toggle response:', response);
    7067                if (!response.success) {
    7168                    alert('Failed to update rule status: ' + response.data);
     
    7572            },
    7673            error: function(xhr, status, error) {
    77                 console.error('Toggle error:', error);
    7874                alert('Error toggling status: ' + error);
    7975                // Revert toggle
     
    171167                    location.reload();
    172168                } else {
    173                     console.error('Failed to save rule:', response.data);
    174169                    alert('Failed to save rule: ' + response.data);
    175170                }
    176171            },
    177172            error: function(xhr, status, error) {
    178                 console.error('AJAX ERROR:', {
    179                     status: status,
    180                     error: error,
    181                     response: xhr.responseText,
    182                     statusCode: xhr.status
    183                 });
    184173                alert('AJAX Error: ' + error);
    185174            }
     
    228217                $('#min-messages').val(conditions.min_messages || '');
    229218            } catch (e) {
    230                 console.warn('Failed to parse conditions JSON:', e);
     219                // Failed to parse conditions JSON
    231220            }
    232221        }
  • convertybot/trunk/assets/js/admin-subscription.js

    r3437100 r3445725  
    291291            },
    292292            success: function(response) {
    293                 console.log('Upgrade response:', response);
    294293                if (response.success && response.data) {
    295294                    if (response.data.upgraded) {
     
    318317            },
    319318            error: function(xhr) {
    320                 console.error('Upgrade API Error:', xhr);
    321319                var error = convertyBotSubscription.strings.unknownError;
    322320
     
    348346        var billingPeriod = $('#billing-period-toggle').is(':checked') ? 'yearly' : 'monthly';
    349347
    350         console.log('Upgrade request:', {
    351             tier: tier,
    352             billingPeriod: billingPeriod,
    353             apiUrl: convertyBotSubscription.apiUrl + '/v1/shops/upgrade'
    354         });
    355 
    356348        // Get tier info for display
    357349        var newTierInfo = tierInfo[tier] || { name: tier, monthlyPrice: '', yearlyPrice: '' };
     
    392384            function() {
    393385                // On cancel - do nothing
    394                 console.log('Upgrade cancelled by user');
    395386            },
    396387            isDowngrade // isDanger flag for styling
  • convertybot/trunk/assets/js/admin-visitor-journeys.js

    r3443877 r3445725  
    4444     */
    4545    function init() {
    46         console.log('Initializing Visitor Journeys Dashboard');
    47         console.log('Using WordPress AJAX URL:', typeof ajaxurl !== 'undefined' ? ajaxurl : 'Not defined');
    48 
    4946        // Validate configuration
    5047        if (!validateConfiguration()) {
     
    6663    function validateConfiguration() {
    6764        if (typeof ajaxurl === 'undefined' || !ajaxurl || ajaxurl.trim() === '') {
    68             console.error('WordPress AJAX URL is missing');
    6965            return false;
    7066        }
     
    127123            e.preventDefault();
    128124            const page = $(this).data('page');
    129             console.log('[Pagination] Clicked page:', page, 'Current page:', currentFilters.page);
    130125            if (page && page !== currentFilters.page) {
    131126                currentFilters.page = page;
    132                 console.log('[Pagination] Loading page:', currentFilters.page);
    133127                loadSessions();
    134             } else {
    135                 console.log('[Pagination] Same page, not reloading');
    136128            }
    137129        });
     
    200192
    201193        const params = buildDateParams();
    202 
    203         // Debug: log NONCE value
    204         console.log('[Overview] NONCE value:', NONCE, 'Config:', config);
    205194
    206195        activeRequests.overview = $.ajax({
     
    218207                    updateOverviewStats(response.data.overview);
    219208                    $('#stats-overview').slideDown();
    220                 } else {
    221                     console.warn('Unexpected response format:', response);
    222209                }
    223210            },
     
    227214                // Don't retry if request was aborted
    228215                if (status === 'abort') {
    229                     console.log('Overview request aborted');
    230216                    return;
    231217                }
    232218
    233                 console.error('Error loading overview stats:', error, 'Status:', status);
    234                 console.error('Response:', xhr.responseText);
    235 
    236219                // Retry logic for network errors
    237220                if (retryCount < MAX_RETRIES && (status === 'timeout' || status === 'error')) {
    238                     console.log(`Retrying overview stats (attempt ${retryCount + 1}/${MAX_RETRIES})...`);
    239221                    setTimeout(function() {
    240222                        loadOverviewStats(retryCount + 1);
     
    285267        };
    286268
    287         console.log('[Sessions] Request data:', requestData, 'NONCE:', NONCE);
    288 
    289269        activeRequests.sessions = $.ajax({
    290270            url: ajaxurl,
     
    296276                hideLoading();
    297277
    298                 console.log('[Sessions] Response:', response);
    299 
    300278                if (response.success && response.data) {
    301279                    sessionsData = response.data;
    302                     console.log('[Sessions] Pagination received:', response.data.pagination);
    303280                    renderSessionsList(response.data);
    304281                    renderPagination(response.data.pagination);
     
    310287                    }
    311288                } else {
    312                     console.warn('Unexpected response format:', response);
    313289                    showError('Unexpected data format received.');
    314290                }
     
    319295                // Don't retry if request was aborted
    320296                if (status === 'abort') {
    321                     console.log('Sessions request aborted');
    322297                    hideLoading();
    323298                    return;
    324299                }
    325300
    326                 console.error('Error loading sessions:', error, 'Status:', status);
    327                 console.error('Response:', xhr.responseText);
    328301                hideLoading();
    329302
    330303                // Retry logic for network errors
    331304                if (retryCount < MAX_RETRIES && (status === 'timeout' || status === 'error')) {
    332                     console.log(`Retrying sessions (attempt ${retryCount + 1}/${MAX_RETRIES})...`);
    333305                    setTimeout(function() {
    334306                        loadSessions(retryCount + 1);
     
    647619                    $('#journey-content').fadeIn();
    648620                } else {
    649                     console.warn('Unexpected response format:', response);
    650621                    showError('Unexpected data format received.');
    651622                }
     
    657628                // Don't retry if request was aborted
    658629                if (status === 'abort') {
    659                     console.log('Journey request aborted');
    660630                    return;
    661631                }
    662632
    663                 console.error('Error loading journey details:', error, 'Status:', status);
    664                 console.error('Response:', xhr.responseText);
    665 
    666633                // Retry logic for network errors
    667634                if (retryCount < MAX_RETRIES && (status === 'timeout' || status === 'error')) {
    668                     console.log(`Retrying journey details (attempt ${retryCount + 1}/${MAX_RETRIES})...`);
    669635                    setTimeout(function() {
    670636                        loadJourneyDetails(sessionId, retryCount + 1);
     
    758724        timeline.forEach(function(item) {
    759725            // Filter out empty/whitespace-only insights before checking
    760             // Handle undefined, null, or empty arrays
    761             const filteredInsights = (item.insights && Array.isArray(item.insights))
    762                 ? item.insights.filter(function(insight) {
    763                     return insight && typeof insight === 'string' && insight.trim().length > 0;
    764                 })
    765                 : [];
     726            // Handle undefined, null, empty arrays, and non-string values
     727            let filteredInsights = [];
     728            if (item.insights && Array.isArray(item.insights)) {
     729                filteredInsights = item.insights.filter(function(insight) {
     730                    // Must be a string and not empty or whitespace-only
     731                    return typeof insight === 'string' && insight.trim();
     732                });
     733            }
    766734
    767735            const itemData = {
     
    781749            let itemHtml = template;
    782750
    783             // Replace simple variables
     751            // Replace simple variables (but NOT {{this}} which is used inside #each loops)
    784752            itemHtml = itemHtml.replace(/\{\{(\w+)\}\}/g, function(match, key) {
     753                if (key === 'this') return match; // Preserve {{this}} for #each processing
    785754                return itemData[key] !== undefined ? itemData[key] : '';
    786755            });
     
    829798                content = content.replace(/\{\{#each insights\}\}([\s\S]*?)\{\{\/each\}\}/g, function(match, itemContent) {
    830799                    return data.insights.map(function(insight) {
    831                         // Only render if insight text is not empty
    832                         if (insight && insight.trim()) {
    833                             return itemContent.replace(/\{\{this\}\}/g, insight);
     800                        // Only render if insight is a string and not empty
     801                        if (typeof insight === 'string' && insight.trim()) {
     802                            return itemContent.replace(/\{\{this\}\}/g, escapeHtml(insight));
    834803                        }
    835804                        return '';
     
    842811        });
    843812
     813        // EXTRA: Remove any remaining empty timeline-insights divs
     814        html = html.replace(/<div class="timeline-insights">\s*<\/div>/g, '');
     815
    844816        // Clean up any remaining template syntax
    845817        html = html.replace(/\{\{#if \w+\}\}/g, '');
     
    850822        return html;
    851823    }
     824
    852825
    853826    /**
     
    998971            notice.fadeOut(function() { $(this).remove(); });
    999972        }, 10000);
    1000 
    1001         // Also log to console for debugging
    1002         console.error('User Error:', message);
    1003973    }
    1004974
  • convertybot/trunk/assets/js/admin.js

    r3444237 r3445725  
    456456    function loadAnalyticsCharts() {
    457457        if (typeof Chart === 'undefined') {
    458             console.warn('Chart.js not loaded');
    459458            return;
    460459        }
     
    621620        }
    622621       
    623         // Log the current state for debugging
    624         console.log('AI Chatbot Toggle State:', {
    625             chatbot_enabled: chatbotEnabled,
    626             auto_open: $('#auto_open').is(':checked'),
    627             engagement_tracking: $('#engagement_tracking').is(':checked'),
    628             sound_enabled: $('#sound_enabled').is(':checked')
    629         });
    630622    }
    631623   
     
    840832                conditions = typeof data.conditions === 'string' ? JSON.parse(data.conditions) : data.conditions;
    841833            } catch (e) {
    842                 console.warn('Failed to parse conditions JSON:', data.conditions);
    843834                conditions = {};
    844835            }
  • convertybot/trunk/assets/js/analytics-comprehensive.js

    r3437100 r3445725  
    5353        this.setupTouchInteractions();
    5454        this.setupAccessibilityFeatures();
    55 
    56         console.log('Comprehensive Analytics Dashboard initialized');
    5755    }
    5856
     
    117115        // Prevent modal close on content click
    118116        $('.modal-content').on('click', (e) => e.stopPropagation());
    119 
    120         console.log('Event listeners setup complete');
    121117    }
    122118
     
    148144        this.initializeBehavioralPatternsChart();
    149145        this.initializeForecastChart();
    150 
    151         console.log('Charts initialization complete');
    152146    }
    153147
     
    928922
    929923            this.websocket.onopen = () => {
    930                 console.log('WebSocket connection established');
    931924                this.updateRealTimeStatus(true);
    932925            };
     
    938931
    939932            this.websocket.onclose = () => {
    940                 console.log('WebSocket connection closed');
    941933                this.updateRealTimeStatus(false);
    942934                // Attempt to reconnect after 5 seconds
     
    965957            this.updateRealTimeMetrics();
    966958        }, this.config.refreshInterval);
    967 
    968         console.log('Polling setup complete');
    969959    }
    970960
     
    984974                break;
    985975            default:
    986                 console.log('Unknown real-time update type:', data.type);
     976                break;
    987977        }
    988978    }
     
    14651455    showMetricDrillDown(metricType) {
    14661456        // This would typically show a modal with detailed breakdown
    1467         console.log('Showing drill-down for:', metricType);
    1468        
    14691457        if (window.aiTrack) {
    14701458            window.aiTrack('metric_drill_down', { metric: metricType });
     
    16781666        document.removeEventListener('keydown', this.handleKeydown);
    16791667        window.removeEventListener('resize', this.handleResize);
    1680 
    1681         console.log('Analytics dashboard destroyed');
    16821668    }
    16831669}
  • convertybot/trunk/assets/js/analytics-enhanced.js

    r3437100 r3445725  
    5959        init() {
    6060            if (!this.shouldTrack()) {
    61                 console.log('Analytics: Tracking disabled due to sampling or privacy settings');
    6261                return;
    6362            }
     
    6968            this.trackPageLoad();
    7069            this.startPeriodicFlush();
    71            
    72             console.log('Analytics: Advanced tracking initialized');
    7370        }
    7471       
     
    421418                this.flush();
    422419            }
    423            
    424             console.log('Analytics: Event tracked', eventType, properties);
    425420        }
    426421       
     
    548543            // Skip if no nonce available (indicates WordPress context issues)
    549544            if (!nonce) {
    550                 console.warn('Analytics: No nonce available, skipping analytics data send');
    551545                return;
    552546            }
     
    600594                   
    601595                    const result = await response.json();
    602                     if (result && !result.success && result.data) {
    603                         console.warn('Analytics: Server returned error:', result.data);
    604                     }
    605                 }
    606                
    607                 console.log('Analytics: Data sent successfully', data.events?.length || 0, 'events');
     596                }
    608597            } catch (error) {
    609                 // Different handling based on error type
    610                 if (error.name === 'AbortError') {
    611                     console.warn('Analytics: Request timed out');
    612                 } else if (error.message.includes('404')) {
    613                     console.warn('Analytics: Endpoint not available, data will be stored for retry');
    614                 } else {
    615                     console.error('Analytics: Failed to send data', error.message);
    616                 }
    617                
    618598                // Store failed events in localStorage for retry (but limit storage)
    619599                if (!isBeacon && data.events && data.events.length > 0) {
     
    636616                localStorage.setItem('convertybot_failed_events', JSON.stringify(failedEvents));
    637617            } catch (error) {
    638                 console.error('Analytics: Failed to store events', error);
     618                // Storage error - silently fail
    639619            }
    640620        }
     
    647627                const failedEvents = JSON.parse(stored);
    648628                if (failedEvents.length === 0) return;
    649                
    650                 console.log('Analytics: Retrying', failedEvents.length, 'failed events');
    651                
     629
    652630                this.sendAnalyticsData({ events: failedEvents, metrics: {}, heatmap: [], performance: {}, funnel: {} });
    653631                localStorage.removeItem('convertybot_failed_events');
    654632            } catch (error) {
    655                 console.error('Analytics: Failed to retry events', error);
     633                // Retry error - silently fail
    656634            }
    657635        }
     
    726704            window.convertyBotAnalytics.trackConversion(type, value, properties);
    727705        };
    728        
    729         console.log('Analytics: Advanced system initialized');
    730706    }
    731707   
  • convertybot/trunk/assets/js/analytics-redesigned.js

    r3437100 r3445725  
    8282            this.setupKeyboardNavigation();
    8383           
    84             console.log('✅ Analytics Dashboard initialized successfully');
    8584            this.announceToScreenReader('Analytics dashboard loaded successfully');
    8685        } catch (error) {
    87             console.error('Failed to initialize Analytics Dashboard:', error);
     86            console.error('Failed to initialize Analytics Dashboard:', error);
    8887            this.showNotification('Failed to initialize dashboard', 'error');
    8988        }
     
    229228            this.measurePerformance('initial_load', performance.now());
    230229        });
    231 
    232         console.log('📋 Event listeners setup complete');
    233230    }
    234231
     
    267264        // Check for accessibility preferences
    268265        this.checkAccessibilityPreferences();
    269 
    270         console.log('♿ Accessibility features setup complete');
    271266    }
    272267
     
    363358    async initializeCharts() {
    364359        if (typeof Chart === 'undefined') {
    365             console.warn('Chart.js not loaded, charts will not be available');
    366360            return;
    367361        }
     
    387381            const loadTime = performance.now() - startTime;
    388382            this.measurePerformance('charts_init', loadTime);
    389            
    390             console.log(`📊 Charts initialized in ${loadTime.toFixed(2)}ms`);
    391383        } catch (error) {
    392384            console.error('Failed to initialize charts:', error);
     
    519511
    520512            this.charts.set('revenue', chart);
    521             console.log('📈 Revenue chart initialized');
    522513        } finally {
    523514            this.showChartLoading('revenue-chart-loading', false);
     
    584575
    585576            this.charts.set('funnel', chart);
    586             console.log('🔽 Funnel chart initialized');
    587577        } catch (error) {
    588578            console.error('Failed to initialize funnel chart:', error);
     
    623613
    624614            this.charts.set('aiGauge', chart);
    625             console.log('🎯 AI Gauge chart initialized');
    626615        } catch (error) {
    627616            console.error('Failed to initialize AI gauge chart:', error);
     
    674663
    675664            this.charts.set('device', chart);
    676             console.log('📱 Device chart initialized');
    677665        } catch (error) {
    678666            console.error('Failed to initialize device chart:', error);
     
    730718
    731719            this.charts.set('heatmap', chart);
    732             console.log('🔥 Heatmap initialized');
    733720        } catch (error) {
    734721            console.error('Failed to initialize heatmap:', error);
     
    809796                const loadTime = performance.now() - startTime;
    810797                this.measurePerformance('data_load', loadTime);
    811                
    812                 console.log(`💾 Dashboard data loaded in ${loadTime.toFixed(2)}ms`);
    813798            } else {
    814799                throw new Error(response.message || 'Failed to load dashboard data');
     
    836821        // Update comparison indicators
    837822        this.updateComparisonIndicators();
    838        
    839         console.log('📊 Dashboard metrics updated');
    840823    }
    841824
     
    918901
    919902            this.websocket.onopen = () => {
    920                 console.log('🔌 WebSocket connected');
    921903                this.updateConnectionStatus(true);
    922904                this.announceToScreenReader('Real-time updates connected');
     
    933915
    934916            this.websocket.onclose = (event) => {
    935                 console.log('🔌 WebSocket disconnected:', event.code);
    936917                this.updateConnectionStatus(false);
    937918               
     
    974955
    975956        this.updateConnectionStatus(true);
    976         console.log('⏰ Polling setup complete');
    977957    }
    978958
     
    995975                break;
    996976            default:
    997                 console.log('Unknown real-time update type:', data.type);
     977                break;
    998978        }
    999979    }
     
    14741454            pullDistance = 0;
    14751455        }, { passive: true });
    1476 
    1477         console.log('👆 Touch interactions setup complete');
    14781456    }
    14791457
     
    15181496            }
    15191497        });
    1520 
    1521         console.log('⌨️ Keyboard navigation setup complete');
    15221498    }
    15231499
     
    17651741            });
    17661742        }
    1767        
    1768         console.log('📊 Event tracked:', eventName, properties);
    17691743    }
    17701744
     
    19391913            this.announcer.parentNode.removeChild(this.announcer);
    19401914        }
    1941 
    1942         console.log('🧹 Analytics dashboard cleanup complete');
    19431915    }
    19441916
     
    19981970    }
    19991971};
    2000 
    2001 console.log('🚀 ConvertyBot Analytics Dashboard JavaScript loaded');
  • convertybot/trunk/assets/js/analytics-websocket.js

    r3437100 r3445725  
    5454    init() {
    5555        if (!this.config.url) {
    56             console.warn('WebSocket URL not configured, falling back to polling');
    5756            this.enableFallbackMode();
    5857            return;
     
    6968    connect() {
    7069        if (this.socket && this.socket.readyState === WebSocket.OPEN) {
    71             console.log('WebSocket already connected');
    7270            return;
    7371        }
     
    8482            url.searchParams.set('client_id', this.getClientId());
    8583
    86             console.log('Connecting to WebSocket:', url.toString());
    87 
    8884            this.socket = new WebSocket(
    8985                url.toString(),
     
    104100    setupSocketEventHandlers() {
    105101        this.socket.onopen = (event) => {
    106             console.log('WebSocket connected');
    107102            this.connectionState = 'connected';
    108103            this.metrics.lastConnected = new Date();
     
    123118
    124119        this.socket.onclose = (event) => {
    125             console.log('WebSocket connection closed:', event.code, event.reason);
    126120            this.connectionState = 'disconnected';
    127121            this.metrics.lastDisconnected = new Date();
     
    170164                    break;
    171165                default:
    172                     console.log('Unknown message type:', message.type);
     166                    break;
    173167            }
    174168
     
    264258        switch (action) {
    265259            case 'server_restart':
    266                 console.log('Server restart detected, will reconnect');
    267260                this.scheduleReconnection(5000); // Wait 5 seconds
    268261                break;
    269262            case 'maintenance_mode':
    270                 console.log('Server entering maintenance mode');
    271263                this.enableFallbackMode();
    272264                break;
     
    420412        defaultChannels.forEach(channel => {
    421413            this.subscribe(channel, (data) => {
    422                 console.log(`Received data for ${channel}:`, data);
     414                // Handle data silently
    423415            });
    424416        });
     
    480472    scheduleReconnection(delay = null) {
    481473        if (!this.shouldReconnect()) {
    482             console.log('Max reconnection attempts reached or conditions not met');
    483474            this.enableFallbackMode();
    484475            return;
     
    489480            this.config.maxReconnectDelay
    490481        );
    491 
    492         console.log(`Scheduling reconnection in ${reconnectDelay}ms (attempt ${this.reconnectCount + 1})`);
    493482
    494483        setTimeout(() => {
     
    508497        // Try fallback URL if available
    509498        if (this.config.fallbackUrl && this.config.url !== this.config.fallbackUrl) {
    510             console.log('Trying fallback WebSocket URL');
    511499            this.config.url = this.config.fallbackUrl;
    512500            this.scheduleReconnection(1000);
     
    520508     */
    521509    enableFallbackMode() {
    522         console.log('Enabling fallback polling mode');
    523510        this.connectionState = 'fallback';
    524511        this.notifyStateChange('fallback');
     
    582569        // Handle online/offline events
    583570        window.addEventListener('online', () => {
    584             console.log('Network connection restored');
    585571            if (this.connectionState === 'disconnected') {
    586572                this.connect();
     
    589575
    590576        window.addEventListener('offline', () => {
    591             console.log('Network connection lost');
    592577            this.pauseConnection();
    593578        });
     
    680665    implementRateLimit(retryAfter) {
    681666        const delay = (retryAfter || 60) * 1000; // Convert to milliseconds
    682         console.log(`Rate limited, waiting ${delay}ms before retry`);
    683        
     667
    684668        this.pauseConnection();
    685669        setTimeout(() => {
     
    693677    updateConfig(newConfig) {
    694678        Object.assign(this.config, newConfig);
    695         console.log('Configuration updated:', newConfig);
    696679    }
    697680
     
    771754        if (this.eventHandlers.hasOwnProperty(`on${event.charAt(0).toUpperCase() + event.slice(1)}`)) {
    772755            this.eventHandlers[`on${event.charAt(0).toUpperCase() + event.slice(1)}`] = handler;
    773         } else {
    774             console.warn(`Unknown event type: ${event}`);
    775756        }
    776757    }
     
    845826        // Clear message queue
    846827        this.messageQueue = [];
    847        
    848         console.log('WebSocket manager destroyed');
    849828    }
    850829}
  • convertybot/trunk/assets/js/chatbot-sounds.js

    r3437100 r3445725  
    5454                this.sounds[soundName]();
    5555            } catch (error) {
    56                 console.warn('Failed to play sound:', soundName, error);
     56                // Failed to play sound
    5757            }
    5858        }
  • convertybot/trunk/assets/js/consent-banner.js

    r3437100 r3445725  
    1515
    1616        init() {
    17             console.log('🍪 [ConsentBanner] Initializing...');
    18 
    1917            this.banner = $('#convertybot-consent-banner');
    2018            this.settingsBtn = $('#ai-consent-settings-btn');
    2119
    2220            if (this.banner.length === 0) {
    23                 console.log('🍪 [ConsentBanner] Banner not found, consent already given');
    2421                return;
    2522            }
    2623
    2724            this.bindEvents();
    28             console.log('✅ [ConsentBanner] Initialized successfully');
    2925        }
    3026
     
    3228            // Accept all button
    3329            $('#ai-consent-accept').on('click', () => {
    34                 console.log('✅ [ConsentBanner] User accepted all cookies');
    3530                this.saveConsent({
    3631                    essential: true,
     
    4540            // Reject non-essential button
    4641            $('#ai-consent-reject').on('click', () => {
    47                 console.log('❌ [ConsentBanner] User rejected non-essential cookies');
    4842                this.saveConsent({
    4943                    essential: true,
     
    5852            // Save custom preferences button
    5953            $('#ai-consent-save').on('click', () => {
    60                 console.log('💾 [ConsentBanner] User saving custom preferences');
    6154                const preferences = {
    6255                    essential: true, // Always true
     
    6760                    advertising: false // Not shown in UI yet
    6861                };
    69                 console.log('📋 [ConsentBanner] Custom preferences:', preferences);
    7062                this.saveConsent(preferences);
    7163            });
     
    7365            // Settings button (to re-open banner)
    7466            this.settingsBtn.on('click', () => {
    75                 console.log('⚙️ [ConsentBanner] Opening consent settings');
    7667                this.showBanner();
    7768            });
     
    8071            $('.ai-consent-overlay').on('click', (e) => {
    8172                if ($(e.target).hasClass('ai-consent-overlay')) {
    82                     console.log('ℹ️ [ConsentBanner] User clicked overlay, showing reject prompt');
    8373                    // Don't close without action - prompt user to make a choice
    8474                    this.showRejectPrompt();
     
    8878
    8979        saveConsent(preferences) {
    90             console.log('📤 [ConsentBanner] Sending consent to server...', preferences);
    91 
    9280            $.ajax({
    9381                url: convertyBotConsent.ajaxUrl,
     
    10088                success: (response) => {
    10189                    if (response.success) {
    102                         console.log('✅ [ConsentBanner] Consent saved successfully', response.data);
    10390                        this.hideBanner();
    10491                        this.notifyConsentChange(preferences);
     
    10996                        // Reload page to apply consent changes
    11097                        setTimeout(() => {
    111                             console.log('🔄 [ConsentBanner] Reloading page to apply consent...');
    11298                            window.location.reload();
    11399                        }, 1000);
    114100                    } else {
    115                         console.error('❌ [ConsentBanner] Failed to save consent', response);
    116101                        this.showToast('Failed to save preferences. Please try again.', 'error');
    117102                    }
    118103                },
    119104                error: (xhr, status, error) => {
    120                     console.error('❌ [ConsentBanner] AJAX error:', error);
    121105                    this.showToast('Network error. Please try again.', 'error');
    122106                }
     
    125109
    126110        showBanner() {
    127             console.log('👁️ [ConsentBanner] Showing banner');
    128111            this.banner.removeClass('hidden').css('display', 'flex');
    129112            $('body').css('overflow', 'hidden'); // Prevent scrolling
     
    131114
    132115        hideBanner() {
    133             console.log('🙈 [ConsentBanner] Hiding banner');
    134116            this.banner.addClass('hidden');
    135117            $('body').css('overflow', ''); // Restore scrolling
     
    157139            });
    158140            window.dispatchEvent(event);
    159 
    160             console.log('📢 [ConsentBanner] Consent change event dispatched', preferences);
    161141
    162142            // Update global tracking SDK if available
     
    168148                };
    169149                window.convertyBotTracker.updateConsent(consentData);
    170                 console.log('✅ [ConsentBanner] Updated tracking SDK with new consent');
    171150            }
    172151        }
  • convertybot/trunk/assets/js/coupon-system-enhanced.js

    r3437100 r3445725  
    6060            // Clean up expired coupons on startup
    6161            this.cleanupExpiredCoupons();
    62            
    63             console.log('Enhanced Coupon System initialized');
    6462        }
    6563       
     
    7371                }
    7472            } catch (error) {
    75                 console.error('Failed to load coupon stats:', error);
     73                // Failed to load coupon stats
    7674            }
    7775        }
     
    8381                localStorage.setItem('convertybot_coupon_stats', JSON.stringify(this.userStats));
    8482            } catch (error) {
    85                 console.error('Failed to save coupon stats:', error);
     83                // Failed to save coupon stats
    8684            }
    8785        }
     
    102100                }
    103101            } catch (error) {
    104                 console.error('Failed to load active coupons:', error);
     102                // Failed to load active coupons
    105103            }
    106104        }
     
    113111                localStorage.setItem('convertybot_active_coupons', JSON.stringify(coupons));
    114112            } catch (error) {
    115                 console.error('Failed to save active coupons:', error);
     113                // Failed to save active coupons
    116114            }
    117115        }
     
    756754        processCouponApplication(coupon) {
    757755            // This would integrate with your cart/checkout system
    758             console.log('Applying coupon:', coupon);
    759            
    760756            // Show success message
    761757            if (window.convertyBotChatbot?.showToast) {
     
    10441040           
    10451041            // This would update a gamification widget in the UI
    1046             console.log('Gamification Status:', {
    1047                 level: currentLevel,
    1048                 progress: progress,
    1049                 stats: this.userStats
    1050             });
    10511042        }
    10521043       
  • convertybot/trunk/assets/js/engagement-tracking-sdk.js

    r3437100 r3445725  
    1414(function(window, document) {
    1515    'use strict';
    16 
    17     // ✅ FIX Bug 6: Disable console logs in production mode
    18     // Check if convertyBotTrackingConfig.debug is true before logging
    19     const isDebugMode = typeof window.convertyBotTrackingConfig !== 'undefined' && window.convertyBotTrackingConfig.debug === true;
    20     if (!isDebugMode) {
    21         const noop = function() {};
    22         // Store originals for potential restoration
    23         window._engagementSDKOriginalConsole = { log: console.log, info: console.info, debug: console.debug };
    24         console.log = noop;
    25         console.info = noop;
    26         console.debug = noop;
    27     }
    2816
    2917    // SDK Configuration
     
    5341    class EngagementTrackingSDK {
    5442        constructor(config = {}) {
    55             console.log('[EngagementSDK DEBUG] Received config:', config);
    56             console.log('[EngagementSDK DEBUG] config.userId:', config.userId);
    57             console.log('[EngagementSDK DEBUG] config.siteId:', config.siteId);
    58 
    5943            this.config = { ...DEFAULT_CONFIG, ...config };
    6044            this.sessionId = null;
     
    6246            this.userId = this.config.userId || window.convertyBotGuestId || null;
    6347            this.siteId = this.config.siteId || null;  // Initialize from config
    64 
    65             console.log('[EngagementSDK DEBUG] After init - this.userId:', this.userId);
    66             console.log('[EngagementSDK DEBUG] After init - window.convertyBotGuestId:', window.convertyBotGuestId);
    67             console.log('[EngagementSDK DEBUG] After init - this.siteId:', this.siteId);
    6848
    6949            this.eventBuffer = [];
     
    9373        async init() {
    9474            try {
    95                 console.log('🚀 [EngagementSDK] Starting initialization...', {
    96                     apiEndpoint: this.config.apiEndpoint,
    97                     siteId: this.config.siteId,
    98                     batchSize: this.config.batchSize,
    99                     flushInterval: this.config.flushInterval
    100                 });
    101 
    10275                // Check privacy compliance
    10376                await this.checkPrivacyCompliance();
    10477
    10578                if (!this.isTrackingEnabled) {
    106                     console.warn('⚠️ [EngagementSDK] Tracking disabled due to privacy settings');
    107                     this.log('Tracking disabled due to privacy settings');
    10879                    return;
    10980                }
    110 
    111                 console.log('✅ [EngagementSDK] Privacy check passed, tracking enabled');
    11281
    11382                // Initialize session
     
    12291                this.trackPageView();
    12392
    124                 console.log('🎉 [EngagementSDK] Initialization complete!', {
    125                     sessionId: this.sessionId,
    126                     userId: this.userId,
    127                     siteId: this.siteId,
    128                     trackingEnabled: this.isTrackingEnabled
    129                 });
    130 
    131                 this.log('Engagement tracking initialized', {
    132                     sessionId: this.sessionId,
    133                     userId: this.userId
    134                 });
    135 
    13693            } catch (error) {
    137                 console.error('❌ [EngagementSDK] Failed to initialize', error);
    138                 this.log('Failed to initialize tracking SDK', error);
     94                console.error('[EngagementSDK] Failed to initialize', error);
    13995            }
    14096        }
     
    152108            // Skip consent check if pointing to backend Node.js API
    153109            if (this.config.apiEndpoint && !this.config.apiEndpoint.includes('/wp-json')) {
    154                 console.log('✅ [EngagementSDK] Using backend API, skipping WordPress consent check');
    155110                return;
    156111            }
     
    180135        async initializeSession() {
    181136            try {
    182                 console.log('🔐 [EngagementSDK] Initializing session...');
    183 
    184137                // Get existing session or create new one
    185138                const existingSession = this.getSessionFromStorage();
    186139
    187140                if (existingSession) {
    188                     console.log('✅ [EngagementSDK] Found existing session', {
    189                         sessionId: existingSession.sessionId,
    190                         userId: existingSession.userId,
    191                         lastActivity: new Date(existingSession.lastActivity).toLocaleString()
    192                     });
    193 
    194141                    // Update session with current userId and siteId from config if they're missing
    195142                    if (!existingSession.userId && this.userId) {
    196                         console.log('🔄 [EngagementSDK] Updating session with userId from config:', this.userId);
    197143                        existingSession.userId = this.userId;
    198144                    }
    199145                    if (!existingSession.siteId && this.siteId) {
    200                         console.log('🔄 [EngagementSDK] Updating session with siteId from config:', this.siteId);
    201146                        existingSession.siteId = this.siteId;
    202147                    }
     
    204149                    var sessionData = existingSession;
    205150                } else {
    206                     console.log('🆕 [EngagementSDK] No existing session, creating new one...');
    207151                    var sessionData = await this.createNewSession();
    208152                }
     
    215159                this.saveSessionToStorage(sessionData);
    216160
    217                 console.log('✅ [EngagementSDK] Session initialized successfully', {
    218                     sessionId: this.sessionId,
    219                     userId: this.userId,
    220                     siteId: this.siteId
    221                 });
    222 
    223161                // Start real-time tracking
    224162                await this.startRealTimeTracking();
    225163
    226164            } catch (error) {
    227                 console.error('❌ [EngagementSDK] Failed to initialize session', error);
    228                 this.log('Failed to initialize session', error);
     165                console.error('[EngagementSDK] Failed to initialize session', error);
    229166                throw error;
    230167            }
     
    233170        async createNewSession() {
    234171            const deviceInfo = this.getDeviceInfo();
    235 
    236             console.log('📝 [EngagementSDK] Creating new session on server', {
    237                 endpoint: this.config.apiEndpoint + '/tracking/session',
    238                 deviceInfo: deviceInfo,
    239                 url: window.location.href
    240             });
    241172
    242173            const response = await this.makeRequest('/tracking/session', {
     
    257188            });
    258189
    259             console.log('✅ [EngagementSDK] Session created successfully', response.data);
    260 
    261190            return response.data;
    262191        }
     
    304233                }
    305234            } catch (error) {
    306                 this.log('Failed to get session from storage', error);
     235                // Silent fail for storage retrieval
    307236            }
    308237            return null;
     
    317246                localStorage.setItem('convertybot_session', JSON.stringify(dataToStore));
    318247            } catch (error) {
    319                 this.log('Failed to save session to storage', error);
     248                // Silent fail for storage save
    320249            }
    321250        }
     
    333262
    334263                this.abTestAssignments = response.data || {};
    335                
     264
    336265                // Store assignments for consistent experience
    337266                localStorage.setItem('convertybot_ab_tests', JSON.stringify(this.abTestAssignments));
    338267
    339268            } catch (error) {
    340                 this.log('Failed to get A/B test assignments', error);
    341269                // Try to load from storage
    342270                try {
     
    678606        trackEvent(eventData) {
    679607            if (!this.isTrackingEnabled) {
    680                 console.warn('⚠️ [EngagementSDK] Tracking disabled - event not tracked', eventData);
    681608                return;
    682609            }
     
    693620            this.eventBuffer.push(event);
    694621
    695             console.log('🎯 [EngagementSDK] Event tracked', {
    696                 type: event.type,
    697                 sessionId: this.sessionId,
    698                 bufferSize: this.eventBuffer.length,
    699                 willFlush: this.eventBuffer.length >= this.config.batchSize,
    700                 eventData: event
    701             });
    702 
    703622            // Flush if buffer is full
    704623            if (this.eventBuffer.length >= this.config.batchSize) {
    705                 console.log('📦 [EngagementSDK] Buffer full, triggering flush', {
    706                     bufferSize: this.eventBuffer.length,
    707                     batchSize: this.config.batchSize
    708                 });
    709624                this.flush();
    710625            }
    711 
    712             this.log('Event tracked', event);
    713626        }
    714627
     
    741654                    userAgent: navigator.userAgent
    742655                }
    743             }).catch(error => {
    744                 this.log('Failed to track product interaction', error);
     656            }).catch(() => {
     657                // Silent fail for product interaction tracking
    745658            });
    746659        }
     
    756669                    ...conversionData
    757670                }
    758             }).catch(error => {
    759                 this.log('Failed to track conversion', error);
     671            }).catch(() => {
     672                // Silent fail for conversion tracking
    760673            });
    761674        }
     
    785698                });
    786699            } catch (error) {
    787                 this.log('Failed to start real-time tracking', error);
     700                // Silent fail for real-time tracking start
    788701            }
    789702        }
     
    793706
    794707            const events = this.eventBuffer.splice(0);
    795             const eventTypes = events.map(e => e.type).join(', ');
    796 
    797             console.log('📤 [EngagementSDK] Sending batch events to server', {
    798                 count: events.length,
    799                 types: eventTypes,
    800                 sessionId: this.sessionId,
    801                 endpoint: this.config.apiEndpoint + '/tracking/events/batch'
    802             });
    803708
    804709            try {
    805                 const response = await this.makeRequest('/tracking/events/batch', {
     710                await this.makeRequest('/tracking/events/batch', {
    806711                    method: 'POST',
    807712                    data: {
     
    814719                });
    815720
    816                 console.log('✅ [EngagementSDK] Batch events sent successfully', {
    817                     count: events.length,
    818                     response: response
    819                 });
    820 
    821                 this.log('Flushed events successfully', { count: events.length });
    822 
    823721            } catch (error) {
    824                 console.error('❌ [EngagementSDK] Failed to send batch events', {
    825                     error: error.message,
    826                     count: events.length,
    827                     eventTypes: eventTypes
    828                 });
    829 
    830                 this.log('Failed to flush events', error);
    831722                // Re-add events to buffer for retry
    832723                this.eventBuffer.unshift(...events);
     
    1101992
    1102993        generateId() {
    1103             return 'xxxx-xxxx-xxxx'.replace(/[x]/g, () => 
     994            return 'xxxx-xxxx-xxxx'.replace(/[x]/g, () =>
    1104995                (Math.random() * 16 | 0).toString(16)
    1105996            );
    1106         }
    1107 
    1108         log(message, data = null) {
    1109             // Always log tracking events for visibility (use debug flag for internal details only)
    1110             const isImportantEvent = message.includes('initialized') ||
    1111                                      message.includes('Session') ||
    1112                                      message.includes('tracked') ||
    1113                                      message.includes('sent') ||
    1114                                      message.includes('failed') ||
    1115                                      message.includes('error');
    1116 
    1117             if (isImportantEvent || this.config.debug) {
    1118                 const emoji = this.getLogEmoji(message);
    1119                 const timestamp = new Date().toLocaleTimeString();
    1120 
    1121                 if (data) {
    1122                     console.log(`${emoji} [EngagementSDK ${timestamp}] ${message}`, data);
    1123                 } else {
    1124                     console.log(`${emoji} [EngagementSDK ${timestamp}] ${message}`);
    1125                 }
    1126             }
    1127         }
    1128 
    1129         getLogEmoji(message) {
    1130             if (message.includes('initialized') || message.includes('Session created')) return '🚀';
    1131             if (message.includes('Page view')) return '📄';
    1132             if (message.includes('Event tracked')) return '🎯';
    1133             if (message.includes('Click')) return '👆';
    1134             if (message.includes('Scroll')) return '📜';
    1135             if (message.includes('Product')) return '🛍️';
    1136             if (message.includes('Batch')) return '📦';
    1137             if (message.includes('sent') || message.includes('Sending')) return '📤';
    1138             if (message.includes('success')) return '✅';
    1139             if (message.includes('failed') || message.includes('error')) return '❌';
    1140             if (message.includes('warning')) return '⚠️';
    1141             return '📊';
    1142997        }
    1143998
  • convertybot/trunk/assets/js/frontend-enhanced.js

    r3437100 r3445725  
    3838            // Use the new EngagementTrackingSDK if available, otherwise fall back to old tracker
    3939            if (window.convertyBotTracker) {
    40                 console.log('🔗 [Frontend] Using EngagementTrackingSDK', {
    41                     sessionId: window.convertyBotTracker.sessionId,
    42                     isTrackingEnabled: window.convertyBotTracker.isTrackingEnabled
    43                 });
    4440                this.engagementTracker = window.convertyBotTracker;
    4541
    4642                // Add compatibility wrapper methods to match old API
    4743                if (!this.engagementTracker._compatibilityWrapped) {
    48                     console.log('🔧 [Frontend] Adding compatibility wrapper to SDK');
    4944                    const originalTrackEvent = this.engagementTracker.trackEvent.bind(this.engagementTracker);
    5045
     
    5348                        if (typeof typeOrData === 'string') {
    5449                            // Old API: trackEvent('event_type', { data })
    55                             console.log('🔄 [Frontend] Tracking event (old API)', {
    56                                 type: typeOrData,
    57                                 data: data
    58                             });
    5950                            originalTrackEvent({
    6051                                type: typeOrData,
     
    6354                        } else {
    6455                            // New API: trackEvent({ type: 'event_type', metadata: {} })
    65                             console.log('🔄 [Frontend] Tracking event (new API)', typeOrData);
    6656                            originalTrackEvent(typeOrData);
    6757                        }
     
    7060                    // Add startSession compatibility method
    7161                    this.engagementTracker.startSession = function(sessionId) {
    72                         console.log('📊 [Frontend] Session started with ID:', sessionId);
    73                         // SDK auto-manages sessions, just log for compatibility
     62                        // SDK auto-manages sessions
    7463                    };
    7564
    7665                    // Add sendFinalStats compatibility method
    7766                    this.engagementTracker.sendFinalStats = function() {
    78                         console.log('📊 [Frontend] Sending final stats...');
    7967                        // Force flush any pending events
    8068                        if (this.flush) {
    81                             console.log('📤 [Frontend] Flushing pending events');
    8269                            this.flush();
    8370                        }
     
    8572
    8673                    this.engagementTracker._compatibilityWrapped = true;
    87                     console.log('✅ [Frontend] Compatibility wrapper added successfully');
    8874                }
    8975            } else {
    90                 console.warn('⚠️ [Frontend] EngagementTrackingSDK not found, using AdvancedEngagementTracker fallback');
    9176                this.engagementTracker = new AdvancedEngagementTracker();
    9277            }
     
    153138                // Setup performance monitoring
    154139                this.startPerformanceMonitoring();
    155                
    156                 console.log('ConvertyBot Chatbot initialized successfully');
    157                
     140
    158141            } catch (error) {
    159142                console.error('Failed to initialize chatbot:', error);
     
    261244                navigator.serviceWorker.register(convertyBotFrontend.serviceWorkerUrl)
    262245                    .then((registration) => {
    263                         console.log('Service Worker registered:', registration);
    264246                    })
    265247                    .catch((error) => {
    266                         console.log('Service Worker registration failed:', error);
    267248                    });
    268249            }
     
    271252        async initSocket() {
    272253            if (!convertyBotFrontend.socketUrl) {
    273                 console.warn('ConvertyBot: Socket URL not configured');
    274254                return;
    275255            }
     
    301281                    const connectionTime = performance.now() - connectionStart;
    302282                    this.performanceMetrics.connectionTime = connectionTime;
    303                    
    304                     console.log(`ConvertyBot: Connected in ${connectionTime.toFixed(2)}ms`);
     283
    305284                    this.isConnected = true;
    306285                    this.isReconnecting = false;
     
    314293               
    315294                this.socket.on('disconnect', (reason) => {
    316                     console.log('ConvertyBot: Disconnected -', reason);
    317295                    this.isConnected = false;
    318296                    this.updateConnectionStatus('offline');
     
    482460                // Save session before navigation
    483461                this.saveSession();
    484                 console.log('💾 Session saved before product navigation');
    485462            });
    486463           
     
    585562                if (response.success) {
    586563                    this.sessionId = response.data.session_id;
    587                     console.log('ConvertyBot: Session started', this.sessionId);
    588                    
     564
    589565                    // Join socket room if connected
    590566                    if (this.socket && this.isConnected) {
     
    730706        isFeedbackHandled(sessionId) {
    731707            if (!sessionId) return false;
    732            
     708
    733709            try {
    734710                const handledFeedback = JSON.parse(localStorage.getItem('convertybot_handled_feedback') || '{}');
    735711                return handledFeedback[sessionId] || false;
    736712            } catch (error) {
    737                 console.warn('Failed to check feedback status:', error);
    738713                return false;
    739714            }
     
    768743                    localStorage.setItem('convertybot_handled_feedback', JSON.stringify(handledFeedback));
    769744                }
    770                
    771                 console.log(`Feedback marked as handled for session ${sessionId} (${action})`);
    772745            } catch (error) {
    773                 console.warn('Failed to mark feedback as handled:', error);
    774746            }
    775747        }
     
    919891           
    920892            if (isWelcomeMessage) {
    921                 console.log('🚫 Welcome message detected - removing products');
    922893                metadata.products = [];
    923894            }
     
    10961067                product_id: product.id || product.product_id || 'unknown',
    10971068                id: product.id || product.product_id || 'unknown',
    1098                
     1069
    10991070                // Basic info
    11001071                name: product.name || product.title || 'Product Name',
    11011072                image_url: product.image_url || product.image || product.featured_image || '/wp-content/uploads/woocommerce-placeholder.png',
    1102                
     1073
    11031074                // Pricing
    11041075                price: price,
     
    11081079                regular_price: price,
    11091080                on_sale: salePrice && parseFloat(salePrice) < parseFloat(price),
    1110                
    1111                 // Rating & Reviews 
     1081
     1082                // Rating & Reviews
    11121083                rating: rating,
    11131084                rating_html: ratingHtml,
    11141085                review_count: product.review_count || product.rating_count || 0,
    1115                
     1086
    11161087                // Availability
    11171088                in_stock: product.in_stock !== false && product.stock_status !== 'outofstock',
    11181089                stock_status: product.stock_status || (product.in_stock !== false ? 'instock' : 'outofstock'),
    11191090                availability_text: product.availability_text || (product.in_stock !== false ? 'In Stock' : 'Out of Stock'),
    1120                
     1091
    11211092                // Additional info
    11221093                short_description: product.short_description || product.excerpt || product.description || '',
     
    11251096                badge: product.badge || (salePrice && parseFloat(salePrice) < parseFloat(price) ? 'Sale' : ''),
    11261097            };
    1127            
    1128             console.log('🔧 Normalized product:', normalizedProduct.name, {
    1129                 price_html: normalizedProduct.price_html,
    1130                 rating_html: normalizedProduct.rating_html,
    1131                 availability_text: normalizedProduct.availability_text
    1132             });
    1133            
     1098
    11341099            return normalizedProduct;
    11351100        }
     
    14251390           
    14261391            if (typeof content !== 'string') return content;
    1427            
    1428             console.log('🧹 Cleaning message content. Original length:', content.length);
    1429            
     1392
    14301393            // Remove ALL product card HTML completely - use more aggressive regex
    14311394            // This regex will match everything from opening <div class="product-card to the last </div>
     
    14491412            // Clean whitespace and normalize
    14501413            content = content.replace(/\s+/g, ' ').replace(/\s*\n\s*/g, ' ').trim();
    1451            
    1452             console.log('✅ Cleaned message content. New length:', content.length);
    1453             console.log('🔍 Final content:', content.substring(0, 200) + '...');
    1454            
     1414
    14551415            return content;
    14561416        }
     
    15161476                audio.play().catch(e => {
    15171477                    // Ignore autoplay policy errors
    1518                     console.log('Could not play sound:', e.message);
    15191478                });
    15201479            } catch (error) {
    1521                 console.log('Sound playback failed:', error.message);
    15221480            }
    15231481        }
     
    18161774                        limit: Math.round(performance.memory.jsHeapSizeLimit / 1048576)
    18171775                    };
    1818                    
    1819                     if (memoryInfo.used > 50) { // 50MB threshold
    1820                         console.warn('High memory usage detected:', memoryInfo);
    1821                     }
    18221776                }, 30000);
    18231777            }
     
    18661820
    18671821        handleSessionInfo(data) {
    1868             console.log('Session info received:', data);
    18691822            // Update UI with session information
    18701823        }
     
    19451898                   
    19461899                    if (sessionAge < maxAge) {
    1947                         console.log('🔄 Loading existing session:', session.sessionId);
    19481900                        this.sessionId = session.sessionId;
    19491901                        this.messageHistory = session.messages || [];
     
    19531905                        return true;
    19541906                    } else {
    1955                         console.log('⏰ Session expired, creating new one');
    19561907                        sessionStorage.removeItem(this.sessionKey);
    19571908                    }
     
    19601911                // Create new session
    19611912                this.sessionId = this.generateSessionId();
    1962                 console.log('🆕 Creating new session:', this.sessionId);
    19631913                return false;
    19641914               
    19651915            } catch (error) {
    1966                 console.error('❌ Error loading session:', error);
    19671916                this.sessionId = this.generateSessionId();
    19681917                return false;
     
    19801929               
    19811930                sessionStorage.setItem(this.sessionKey, JSON.stringify(sessionData));
    1982                 console.log('💾 Session saved:', this.sessionId);
    19831931            } catch (error) {
    1984                 console.error('❌ Error saving session:', error);
    19851932            }
    19861933        },
     
    19881935        restoreMessages() {
    19891936            if (this.messageHistory.length > 0) {
    1990                 console.log('📱 Restoring', this.messageHistory.length, 'messages');
    1991                
    19921937                // Clear current messages
    19931938                $('#chatbot-messages').empty();
     
    20171962                this.preferences = stored ? JSON.parse(stored) : {};
    20181963            } catch (error) {
    2019                 console.warn('Failed to load preferences:', error);
    20201964                this.preferences = {};
    20211965            }
     
    20391983                this.storage.setItem(this.prefix + 'preferences', JSON.stringify(this.preferences));
    20401984            } catch (error) {
    2041                 console.warn('Failed to save preferences:', error);
    20421985            }
    20431986        }
     
    25212464                localStorage.setItem('convertybot_coupons', JSON.stringify(couponsData));
    25222465            } catch (error) {
    2523                 console.warn('Failed to save coupons:', error);
    25242466            }
    25252467        }
     
    25402482                }
    25412483            } catch (error) {
    2542                 console.warn('Failed to load saved coupons:', error);
    25432484            }
    25442485        }
  • convertybot/trunk/assets/js/frontend.js

    r3445596 r3445725  
    66    'use strict';
    77
    8     // ✅ FIX Bug 6: Disable console logs in production mode
    9     // Set convertyBotConfig.debug = true to enable logs
    10     const isDebugMode = typeof convertyBotConfig !== 'undefined' && convertyBotConfig.debug === true;
    11     if (!isDebugMode) {
    12         // Store original console methods for potential restoration
    13         const originalConsole = {
    14             log: console.log,
    15             warn: console.warn,
    16             info: console.info,
    17             debug: console.debug
    18         };
    19         // Silence non-error logs in production
    20         console.log = function() {};
    21         console.info = function() {};
    22         console.debug = function() {};
    23         // Keep console.warn and console.error for important issues
    24         // Restore console for debugging: window.restoreConsole = function() { Object.assign(console, originalConsole); }
    25         window._originalConsole = originalConsole;
    26     }
    27 
    28     // ✅ FIX: Track page load time for engagement tracking
     8    // Track page load time for engagement tracking
    299    if (!window.pageLoadTime) {
    3010        window.pageLoadTime = Date.now();
    31         console.log('⏱️ Page load time tracked:', window.pageLoadTime);
    3211    }
    3312
     
    4423        // Initialize the chat
    4524        init: function() {
    46             console.log('Initializing ConvertyBot Chatbot...');
    47 
    4825            // Check if config exists
    4926            if (typeof convertyBotConfig === 'undefined') {
     
    5633            if (window.convertyBotGuestId) {
    5734                this.guestId = window.convertyBotGuestId;
    58                 console.log('👤 Guest ID (from global):', this.guestId);
    5935            } else {
    6036                this.guestId = this.getOrCreateGuestId();
    61                 console.log('👤 Guest ID (created):', this.guestId);
    6237            }
    6338
     
    10075            }
    10176
    102             // CRITICAL: Check if guest needs migration to logged-in user
     77            // CRITICAL: Check if guest needs migration to logged-in user
    10378            this.checkAndTriggerMigration();
    104 
    105             console.log('ConvertyBot Chatbot initialized successfully');
    10679        },
    10780
     
    11992            const guestId = this.getCookie('convertybot_guest_id');
    12093            if (!guestId) {
    121                 console.log('No guest ID cookie found, migration not needed');
    12294                return;
    12395            }
     
    12698            const migrationKey = 'convertybot_migrated_' + convertyBotConfig.userId;
    12799            if (localStorage.getItem(migrationKey) === guestId) {
    128                 console.log('Migration already completed for this user/guest combination');
    129100                return;
    130101            }
    131 
    132             console.log('🔄 Triggering guest-to-user migration...', {
    133                 guestId: guestId,
    134                 userId: convertyBotConfig.userId
    135             });
    136102
    137103            // Trigger migration via AJAX
     
    151117                success: (response) => {
    152118                    if (response.success) {
    153                         console.log('✅ Guest data migration successful:', response.data);
    154119                        // Mark migration as done
    155120                        localStorage.setItem(migrationKey, guestId);
    156121                        // Note: Backend MongoDB migration is handled by the PHP AJAX handler
    157122                    } else {
    158                         console.error('Guest data migration failed:', response.data);
     123                        console.error('Guest data migration failed:', response.data);
    159124                    }
    160125                },
    161126                error: (xhr, status, error) => {
    162                     console.error('Guest data migration AJAX error:', error);
     127                    console.error('Guest data migration AJAX error:', error);
    163128                }
    164129            });
     
    202167                        if (response.success && response.data.session_id) {
    203168                            this.sessionId = response.data.session_id;
    204                             console.log('Chat session started:', this.sessionId, convertyBotConfig.isLoggedIn ? '(logged-in user)' : '(guest)');
    205169                            // Save the session with the new backend session ID
    206170                            this.saveSession();
     
    211175                    }
    212176                });
    213             } else {
    214                 console.log('Using existing session:', this.sessionId);
    215177            }
    216178        },
     
    228190                e.preventDefault();
    229191                e.stopPropagation();
    230                 console.log('Close button clicked');
    231192                self.closeChat();
    232193            });
     
    236197                e.preventDefault();
    237198                e.stopPropagation();
    238                 console.log('Minimize button clicked');
    239199                self.closeChat();
    240200            });
     
    264224                    // Save session before navigation
    265225                    ConvertyBotChat.saveSession();
    266                     console.log('💾 Session saved before product navigation');
    267226                    window.location.href = productUrl; // Open in same page
    268227                }
     
    288247                // Save session (non-blocking)
    289248                ConvertyBotChat.saveSession();
    290                 console.log('💾 Session saved, opening in new tab');
    291249
    292250                // Reset after 1 second
     
    336294                // Save session (non-blocking)
    337295                ConvertyBotChat.saveSession();
    338                 console.log('💾 Session saved, opening in new tab from modal');
    339296
    340297                // Reset after 1 second
     
    393350        // Open chat window
    394351        openChat: function() {
    395             console.log('Opening chat...');
    396352            const widget = $('#convertybot-widget');
    397353            const chatWindow = $('#convertybot-chat-window');
     
    420376        // Close chat window
    421377        closeChat: function() {
    422             console.log('Closing chat...');
    423378            const widget = $('#convertybot-widget');
    424379            const chatWindow = $('#convertybot-chat-window');
     
    438393            // Track event
    439394            this.trackEvent('chat_closed');
    440             console.log('Chat closed, button shown');
    441395        },
    442396       
     
    467421            this.showTyping();
    468422           
    469             // ✅ FIX: Collect engagement data before sending
     423            // Collect engagement data before sending
    470424            const engagementData = this.collectEngagementData();
    471 
    472             console.log('📊 Engagement data collected:', engagementData);
    473425
    474426            // Send to backend
     
    511463                    this.hideTyping();
    512464
    513                     console.log('========================================');
    514                     console.log('🔍 RESPONSE RECEIVED FROM BACKEND');
    515                     console.log('========================================');
    516                     console.log('Full response:', response);
    517                     console.log('response.success:', response.success);
    518                     console.log('response.data exists?', !!response.data);
    519 
    520465                    if (response.success && response.data) {
    521                         console.log('✅ Response is successful and has data');
    522                         console.log('response.data.ai_response exists?', !!response.data.ai_response);
    523 
    524                         if (response.data.ai_response) {
    525                             console.log('📊 AI Response structure:');
    526                             console.log('- message exists?', !!response.data.ai_response.message);
    527                             console.log('- products exists?', !!response.data.ai_response.products);
    528                             console.log('- coupons exists?', !!response.data.ai_response.coupons);
    529                             console.log('- metadata exists?', !!response.data.ai_response.metadata);
    530                         }
    531 
    532466                        // Add AI response
    533467                        if (response.data.ai_response && response.data.ai_response.message) {
     
    536470                            if (response.data.ai_response.products && response.data.ai_response.products.length > 0) {
    537471                                products = response.data.ai_response.products;
    538                                 console.log('📦 Products found (direct path):', products.length);
    539472                            } else if (response.data.ai_response.metadata && response.data.ai_response.metadata.products) {
    540473                                products = response.data.ai_response.metadata.products;
    541                                 console.log('📦 Products found (metadata):', products.length);
    542474                            }
    543475
    544476                            // Extract coupons from response (check direct path first, then metadata)
    545                             console.log('🎟️ CHECKING FOR COUPONS...');
    546                             console.log('- response.data.ai_response.coupons:', response.data.ai_response.coupons);
    547                             console.log('- Is array?', Array.isArray(response.data.ai_response.coupons));
    548                             console.log('- Length:', response.data.ai_response.coupons ? response.data.ai_response.coupons.length : 0);
    549 
    550477                            let coupons = null;
    551478                            if (response.data.ai_response.coupons && response.data.ai_response.coupons.length > 0) {
    552479                                coupons = response.data.ai_response.coupons;
    553                                 console.log('✅ 🎟️ Coupons received (DIRECT PATH):', coupons.length);
    554                                 console.log('Coupon details:', coupons);
    555480                            } else if (response.data.ai_response.metadata && response.data.ai_response.metadata.coupons && response.data.ai_response.metadata.coupons.length > 0) {
    556481                                coupons = response.data.ai_response.metadata.coupons;
    557                                 console.log('✅ 🎟️ Coupons received (METADATA PATH):', coupons.length);
    558                                 console.log('Coupon details:', coupons);
    559                             } else {
    560                                 console.warn('⚠️ NO COUPONS FOUND in response');
    561                                 console.log('Checked paths:');
    562                                 console.log('1. response.data.ai_response.coupons:', response.data.ai_response.coupons);
    563                                 console.log('2. response.data.ai_response.metadata.coupons:', response.data.ai_response.metadata?.coupons);
    564482                            }
    565483
    566484                            // Store products BEFORE adding message (critical for persistence)
    567485                            if (products && products.length > 0) {
    568                                 console.log('Storing products for persistence:', products.length);
    569486                                this.lastProductsData = products;
    570487                                this.allProducts = products;
     
    574491                            }
    575492
    576                             // ✅ FIX: Store coupons BEFORE adding message (for persistence like products)
     493                            // Store coupons BEFORE adding message (for persistence like products)
    577494                            if (coupons && coupons.length > 0) {
    578                                 console.log('Storing coupons for persistence:', coupons.length);
    579495                                this.lastCouponsData = coupons;
    580496                            } else {
     
    586502
    587503                            // Show coupons inline if available (show BEFORE products for better visibility)
    588                             console.log('🎯 About to display coupons...');
    589                             console.log('- coupons variable:', coupons);
    590                             console.log('- coupons is truthy?', !!coupons);
    591504                            if (coupons) {
    592                                 console.log('✅ Calling showCoupons() with', coupons.length, 'coupons');
    593505                                this.showCoupons(coupons);
    594                                 console.log('✅ showCoupons() called successfully');
    595                             } else {
    596                                 console.warn('❌ NOT calling showCoupons() because coupons variable is', coupons);
    597506                            }
    598507
    599508                            // Show products inline if available
    600509                            if (products) {
    601                                 console.log('Showing products:', products.length);
    602510                                this.showProducts(products);
    603511                            }
    604 
    605                             console.log('========================================');
    606                             console.log('✅ RESPONSE PROCESSING COMPLETE');
    607                             console.log('========================================');
    608512
    609513                            // Add suggestions if available
     
    709613        showProducts: function(products) {
    710614            if (!products || products.length === 0) {
    711                 console.log('⚠️ No products to show');
    712615                return;
    713616            }
    714 
    715             console.log('📦 Showing products:', products.length, 'total');
    716617
    717618            // Store all products for modal and for persistence
     
    724625
    725626            if (messageBubble.length === 0) {
    726                 console.log('⚠️ No message bubble found');
    727627                return;
    728628            }
     
    730630            // Show only first 3 products inline
    731631            const displayProducts = products.slice(0, 3);
    732             console.log('📦 Displaying', displayProducts.length, 'products inline');
    733632           
    734633            // Create products HTML to insert INSIDE the message bubble
     
    767666            // Add "See More Products" button if there are more than 3 products
    768667            if (products.length > 3) {
    769                 console.log('✅ Adding "Voir plus" button for', products.length - 3, 'more products');
    770668                productsHtml += `
    771669                    <div class="ai-more-products-section">
     
    778676                    </div>
    779677                `;
    780             } else {
    781                 console.log('ℹ️ Only', products.length, 'products, no "Voir plus" button needed');
    782678            }
    783679           
     
    872768        // Show coupons
    873769        showCoupons: function(coupons) {
    874             console.log('========================================');
    875             console.log('🎟️ showCoupons() FUNCTION CALLED');
    876             console.log('========================================');
    877             console.log('Coupons parameter:', coupons);
    878             console.log('Coupons type:', typeof coupons);
    879             console.log('Is array?', Array.isArray(coupons));
    880             console.log('Length:', coupons ? coupons.length : 'N/A');
    881 
    882770            if (!coupons || coupons.length === 0) {
    883                 console.warn('❌ No coupons to show (empty or null)');
    884771                return;
    885772            }
    886773
    887             console.log('✅ Coupons validation passed, proceeding with', coupons.length, 'coupon(s)');
    888 
    889774            // Find the latest bot message
    890             console.log('🔍 Looking for latest bot message...');
    891775            const lastBotMessage = $('.convertybot-message.bot').last();
    892             console.log('Last bot message found?', lastBotMessage.length > 0);
    893 
    894776            const messageBubble = lastBotMessage.find('.message-bubble');
    895             console.log('Message bubble found?', messageBubble.length > 0);
    896777
    897778            if (messageBubble.length === 0) {
    898                 console.error('No message bubble found for coupon - cannot display');
     779                console.error('No message bubble found for coupon - cannot display');
    899780                return;
    900781            }
    901782
    902             console.log('✅ Message bubble ready, creating coupon HTML...');
    903 
    904             // ✅ FIX: Use shared generateCouponHtml function to avoid code duplication
     783            // Use shared generateCouponHtml function to avoid code duplication
    905784            const couponsHtml = this.generateCouponHtml(coupons);
    906785
    907             console.log('📝 Coupon HTML created, length:', couponsHtml.length, 'characters');
    908             console.log('HTML preview:', couponsHtml.substring(0, 200) + '...');
    909 
    910786            // Append coupon HTML INSIDE the message bubble
    911             console.log('📌 Appending coupon HTML to message bubble...');
    912787            messageBubble.append(couponsHtml);
    913             console.log('✅ Coupon HTML appended successfully');
    914788
    915789            // Scroll to show new content
    916790            const messagesContainer = $('#convertybot-chat-messages');
    917791            messagesContainer.scrollTop(messagesContainer[0].scrollHeight);
    918 
    919             console.log('========================================');
    920             console.log('✅ COUPONS DISPLAYED SUCCESSFULLY');
    921             console.log('========================================');
    922792        },
    923793
     
    926796            if (navigator.clipboard && navigator.clipboard.writeText) {
    927797                navigator.clipboard.writeText(code).then(() => {
    928                     console.log('✅ Coupon code copied:', code);
    929798                    // Show a brief success message
    930799                    const btn = $(`.coupon-copy-btn[data-code="${code}"]`);
     
    955824            try {
    956825                document.execCommand('copy');
    957                 console.log('✅ Coupon code copied (fallback):', code);
    958826            } catch (err) {
    959827                console.error('Failed to copy:', err);
     
    965833        addToCart: function(productId) {
    966834            // This would integrate with WooCommerce cart
    967             console.log('Adding product to cart:', productId);
    968835            // You can customize this based on your e-commerce platform
    969836        },
     
    1011878                        audio.volume = convertyBotConfig.soundVolume || 0.3;
    1012879                        audio.play().catch(() => {
    1013                             console.debug('Notification sound disabled - could not play');
    1014880                            convertyBotConfig.soundEnabled = false;
    1015881                        });
    1016882                    } catch (fallbackError) {
    1017                         console.debug('Audio notifications not supported');
    1018883                        convertyBotConfig.soundEnabled = false;
    1019884                    }
     
    12111076                    guestId = 'guest_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    12121077                    localStorage.setItem(GUEST_ID_KEY, guestId);
    1213                     console.log('🆕 Created new persistent guest ID:', guestId);
    1214                 } else {
    1215                     console.log('📌 Using existing guest ID:', guestId);
    12161078                }
    12171079
     
    12301092                    secureFlag;
    12311093
    1232                 console.log('🍪 Guest ID saved to cookie for PHP access (HTTPS: ' + isHttps + ')');
    1233 
    12341094                return guestId;
    12351095            } catch (error) {
    12361096                // Fallback if localStorage is not available
    1237                 console.warn('localStorage not available, using session-based guest ID');
    12381097                return 'guest_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    12391098            }
     
    12701129                    }
    12711130                } catch (e) {
    1272                     console.warn('Could not get engagement SDK data:', e);
    1273                 }
    1274             }
    1275 
    1276             console.log('📊 Collected engagement data:', data);
     1131                    // Silently handle SDK data retrieval errors
     1132                }
     1133            }
     1134
    12771135            return data;
    12781136        },
    12791137
    1280         // ✅ FIX: Detect WooCommerce product from page
     1138        // Detect WooCommerce product from page
    12811139        detectWooCommerceProduct: function() {
    12821140            // Check if we're on a product page
    12831141            const productElement = $('.product, .single-product, .woocommerce-product');
    12841142            if (productElement.length === 0) {
    1285                 console.log('❌ Not a product page');
    12861143                return null;
    12871144            }
     
    12941151
    12951152            if (!productName) {
    1296                 console.log('❌ Could not detect product name');
    12971153                return null;
    12981154            }
     
    13061162            };
    13071163
    1308             console.log('✅ Product detected:', product);
    13091164            return product;
    13101165        },
     
    13451200                    const session = this.decryptData(sessionData);
    13461201                    if (!session) {
    1347                         console.log('❌ Failed to decrypt session, creating new one');
    13481202                        localStorage.removeItem(this.sessionKey);
    13491203                        return false;
     
    13631217                    if (inactivityTime >= sessionTimeout && browserWasClosed) {
    13641218                        // Session expired AND browser was closed - start fresh
    1365                         console.log('🆕 New browser session detected (timeout + browser was closed)');
    13661219                        localStorage.removeItem(this.sessionKey);
    13671220                        return false;
     
    13701223                    if (inactivityTime < sessionTimeout) {
    13711224                        // Session is still valid - load it (works across tabs!)
    1372                         console.log('🔄 Loading existing session:', session.sessionId, '(shared across tabs)');
    13731225                        this.sessionId = session.sessionId;
    13741226                        this.messageHistory = session.messages || [];
     
    13801232                        // Session timed out but browser wasn't closed
    13811233                        // This means user was inactive for 30+ min but kept browser open
    1382                         console.log('⏰ Session expired (inactive for', Math.round(inactivityTime / 60000), 'minutes)');
    13831234                        localStorage.removeItem(this.sessionKey);
    13841235                        return false;
     
    13871238
    13881239                // No existing session found
    1389                 console.log('🆕 No existing session found, will create new one');
    13901240                return false;
    13911241
    13921242            } catch (error) {
    1393                 console.error('Error loading session:', error);
     1243                console.error('Error loading session:', error);
    13941244                return false;
    13951245            }
     
    14201270                if (encryptedData) {
    14211271                    localStorage.setItem(this.sessionKey, encryptedData);
    1422                     console.log('🔒 Session saved (shared across tabs):', this.sessionId);
    14231272                } else {
    1424                     console.error('Failed to encrypt session data');
     1273                    console.error('Failed to encrypt session data');
    14251274                }
    14261275            } catch (error) {
    1427                 console.error('Error saving session:', error);
     1276                console.error('Error saving session:', error);
    14281277            }
    14291278        },
     
    14311280        restoreMessages: function() {
    14321281            if (this.messageHistory.length > 0) {
    1433                 console.log('📱 Restoring', this.messageHistory.length, 'messages');
    14341282               
    14351283                // Clear current messages
     
    14491297        createNewLocalSession: function() {
    14501298            this.sessionId = 'sess_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    1451             console.log('🆕 Created new local session:', this.sessionId);
    14521299            this.saveSession();
    14531300        },
     
    14771324            const messageBubble = justAddedMessage.find('.message-bubble');
    14781325
    1479             // ✅ FIX: If message has coupons, render them DIRECTLY into the message bubble
     1326            // If message has coupons, render them DIRECTLY into the message bubble
    14801327            // (Don't use showCoupons which uses a general selector that might fail during rapid restoration)
    14811328            if (message.coupons && message.coupons.length > 0 && messageBubble.length > 0) {
    1482                 console.log('📱 Restoring coupons directly:', message.coupons.length);
    14831329                const couponHtml = this.generateCouponHtml(message.coupons);
    14841330                messageBubble.append(couponHtml);
  • convertybot/trunk/assets/js/guest-id-cookie.js

    r3437100 r3445725  
    4747        // Verify cookie was set
    4848        const verification = getCookie(name);
    49         if (verification === value) {
    50             console.log('[Guest ID] ✅ Cookie set successfully:', value);
    51             return true;
    52         } else {
    53             console.error('[Guest ID] ❌ Failed to set cookie. Got:', verification);
    54             return false;
    55         }
     49        return verification === value;
    5650    }
    5751
     
    6559
    6660            if (guestId) {
    67                 console.log('[Guest ID] 📌 Found in cookie:', guestId);
    68 
    6961                // Also sync to localStorage
    7062                try {
    7163                    localStorage.setItem(GUEST_ID_KEY, guestId);
    7264                } catch (e) {
    73                     console.warn('[Guest ID] Could not sync to localStorage:', e);
     65                    // Silent fail for localStorage
    7466                }
    7567
     
    8173                guestId = localStorage.getItem(GUEST_ID_KEY);
    8274                if (guestId) {
    83                     console.log('[Guest ID] 📦 Found in localStorage:', guestId);
    8475                    // Create cookie from localStorage value
    8576                    setCookie(COOKIE_NAME, guestId, 365);
     
    8778                }
    8879            } catch (e) {
    89                 console.warn('[Guest ID] Could not access localStorage:', e);
     80                // Silent fail for localStorage
    9081            }
    9182
    9283            // Step 3: Generate new guest ID
    9384            guestId = 'guest_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    94             console.log('[Guest ID] 🆕 Created new ID:', guestId);
    9585
    9686            // Save to both cookie and localStorage
    97             const cookieSuccess = setCookie(COOKIE_NAME, guestId, 365);
     87            setCookie(COOKIE_NAME, guestId, 365);
    9888
    9989            try {
    10090                localStorage.setItem(GUEST_ID_KEY, guestId);
    10191            } catch (e) {
    102                 console.warn('[Guest ID] Could not save to localStorage:', e);
    103             }
    104 
    105             if (!cookieSuccess) {
    106                 console.error('[Guest ID] ⚠️ WARNING: Cookie creation failed! Purchase tracking may not work!');
     92                // Silent fail for localStorage
    10793            }
    10894
     
    11096
    11197        } catch (error) {
    112             console.error('[Guest ID] Critical error:', error);
    11398            // Return a session-based fallback
    11499            return 'guest_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
     
    126111        const cookieValue = getCookie(COOKIE_NAME);
    127112        if (cookieValue !== guestId) {
    128             console.warn('[Guest ID] Cookie mismatch, forcing recreate...');
    129113            setCookie(COOKIE_NAME, guestId, 365);
    130114        }
     
    132116        // Make guest ID globally available
    133117        window.convertyBotGuestId = guestId;
    134 
    135         console.log('[Guest ID] ✅ Ready:', guestId);
    136118    }
    137119
  • convertybot/trunk/assets/js/migration-handler.js

    r3437100 r3445725  
    88
    99    var MigrationHandler = {
    10         debug: true,
    11 
    12         log: function(message, data) {
    13             if (this.debug) {
    14                 if (data) {
    15                     console.log('[ConvertyBot Migration] ' + message, data);
    16                 } else {
    17                     console.log('[ConvertyBot Migration] ' + message);
    18                 }
    19             }
    20         },
    21 
    22         error: function(message, data) {
    23             console.error('[ConvertyBot Migration ERROR] ' + message, data || '');
    24         },
    25 
    2610        init: function() {
    27             this.log('========================================');
    28             this.log('Migration Handler Initialized');
    29             this.log('========================================');
    30 
    3111            // Check if config is available
    3212            if (typeof convertyBotConfig === 'undefined') {
    33                 this.log('Config not available, waiting...');
    3413                return;
    3514            }
    3615
    37             this.log('User logged in: ' + convertyBotConfig.isLoggedIn);
    38             this.log('User ID: ' + convertyBotConfig.userId);
    39             this.log('User Email: ' + convertyBotConfig.userEmail);
    40             this.log('User Name: ' + convertyBotConfig.userName);
    41 
    4216            // Only proceed if user is logged in
    4317            if (!convertyBotConfig.isLoggedIn || !convertyBotConfig.userId) {
    44                 this.log('User not logged in, migration not needed');
    4518                return;
    4619            }
     
    4821            // Get guest ID from multiple sources
    4922            var guestId = this.getGuestId();
    50             this.log('Guest ID found: ' + guestId);
    5123
    5224            if (!guestId) {
    53                 this.log('No guest ID found, nothing to migrate');
    5425                return;
    5526            }
     
    5930            var alreadyMigrated = localStorage.getItem(migrationKey);
    6031
    61             this.log('Migration key: ' + migrationKey);
    62             this.log('Already migrated: ' + alreadyMigrated);
    63 
    6432            if (alreadyMigrated === 'success') {
    65                 this.log('Migration already completed successfully');
    6633                return;
    6734            }
    6835
    6936            // Force migration
    70             this.log('🔄 Starting forced migration...');
    7137            this.triggerMigration(guestId, migrationKey);
    7238        },
     
    7642            var guestId = localStorage.getItem('convertybot_guest_id');
    7743            if (guestId) {
    78                 this.log('Found guestId in localStorage: ' + guestId);
    7944                return guestId;
    8045            }
     
    8348            guestId = this.getCookie('convertybot_guest_id');
    8449            if (guestId) {
    85                 this.log('Found guestId in cookie: ' + guestId);
    8650                return guestId;
    8751            }
     
    9054            guestId = sessionStorage.getItem('convertybot_guest_id');
    9155            if (guestId) {
    92                 this.log('Found guestId in sessionStorage: ' + guestId);
    9356                return guestId;
    9457            }
     
    11376            };
    11477
    115             this.log('Migration data:', migrationData);
    116 
    11778            $.ajax({
    11879                url: convertyBotConfig.ajaxUrl,
     
    12485                },
    12586                success: function(response) {
    126                     self.log('Migration response:', response);
    127 
    12887                    if (response.success) {
    129                         self.log('✅ Migration successful!', response.data);
    13088                        // Mark as migrated
    13189                        localStorage.setItem(migrationKey, 'success');
     
    13492                        self.triggerBackendMigration(guestId, migrationData);
    13593                    } else {
    136                         self.error('Migration failed:', response.data);
    13794                        localStorage.setItem(migrationKey, 'failed');
    13895                    }
    13996                },
    14097                error: function(xhr, status, error) {
    141                     self.error('Migration AJAX error:', {
    142                         status: status,
    143                         error: error,
    144                         response: xhr.responseText
    145                     });
    14698                    localStorage.setItem(migrationKey, 'error');
    14799                }
     
    150102
    151103        triggerBackendMigration: function(guestId, migrationData) {
    152             var self = this;
    153 
    154104            // Also call the backend API directly
    155105            if (!convertyBotConfig.apiUrl) {
    156                 this.log('No API URL configured, skipping direct backend call');
    157106                return;
    158107            }
     
    160109            var apiKey = this.getApiKey();
    161110            if (!apiKey) {
    162                 this.log('No API key available, skipping direct backend call');
    163111                return;
    164112            }
    165 
    166             this.log('Calling backend API directly...');
    167113
    168114            $.ajax({
     
    183129                        last_name: ''
    184130                    }
    185                 }),
    186                 success: function(response) {
    187                     self.log('Backend API migration response:', response);
    188                 },
    189                 error: function(xhr, status, error) {
    190                     self.log('Backend API error (non-critical):', error);
    191                 }
     131                })
    192132            });
    193133        },
  • convertybot/trunk/assets/js/product-cards-handler.js

    r3437100 r3445725  
    115115    // Compatibility - ensure products are stored for modal use
    116116    document.addEventListener('DOMContentLoaded', function() {
    117         if (window.ConvertyBotChat) {
    118             console.log('Product cards handler initialized');
    119         }
     117        // Handler initialized
    120118    });
    121119   
  • convertybot/trunk/assets/js/product-showcase-enhanced.js

    r3437100 r3445725  
    6969            this.initializePersonalization();
    7070            this.setupRealtimeConnection();
    71            
    72             console.log('Enhanced Product Showcase initialized');
    7371        }
    7472       
     
    10731071        handleQuickView(productId) {
    10741072            // Show quick view modal (would need to be implemented)
    1075             console.log('Quick view for product:', productId);
    1076            
     1073
    10771074            // Analytics
    10781075            if (window.aiTrack) {
  • convertybot/trunk/assets/js/service-worker.js

    r3437100 r3445725  
    4040 */
    4141self.addEventListener('install', (event) => {
    42     console.log('Service Worker: Installing...');
    43    
    4442    event.waitUntil(
    4543        caches.open(CACHE_NAME)
    4644            .then((cache) => {
    47                 console.log('Service Worker: Caching static assets');
    4845                return cache.addAll(STATIC_CACHE_ASSETS);
    4946            })
    5047            .then(() => {
    51                 console.log('Service Worker: Installation complete');
    5248                return self.skipWaiting();
    5349            })
     
    6258 */
    6359self.addEventListener('activate', (event) => {
    64     console.log('Service Worker: Activating...');
    65    
    6660    event.waitUntil(
    6761        Promise.all([
     
    7266                        .filter((cacheName) => cacheName !== CACHE_NAME)
    7367                        .map((cacheName) => {
    74                             console.log('Service Worker: Deleting old cache', cacheName);
    7568                            return caches.delete(cacheName);
    7669                        })
     
    7972            // Take control of all clients
    8073            self.clients.claim()
    81         ]).then(() => {
    82             console.log('Service Worker: Activation complete');
    83         })
     74        ])
    8475    );
    8576});
     
    129120        return networkResponse;
    130121    } catch (error) {
    131         console.log('Service Worker: Network failed, trying cache', error);
    132        
    133122        const cachedResponse = await caches.match(request);
    134123        if (cachedResponse) {
     
    169158        return networkResponse;
    170159    } catch (error) {
    171         console.error('Service Worker: Cache-first failed', error);
    172160        throw error;
    173161    }
     
    189177        return networkResponse;
    190178    }).catch((error) => {
    191         console.log('Service Worker: Network update failed', error);
     179        // Network update failed
    192180    });
    193181   
     
    221209self.addEventListener('sync', (event) => {
    222210    if (event.tag === 'background-message-sync') {
    223         console.log('Service Worker: Background sync triggered');
    224211        event.waitUntil(syncPendingMessages());
    225212    }
     
    233220        // Get pending messages from IndexedDB
    234221        const pendingMessages = await getPendingMessages();
    235        
     222
    236223        if (pendingMessages.length === 0) {
    237             console.log('Service Worker: No pending messages to sync');
    238224            return;
    239225        }
    240        
    241         console.log(`Service Worker: Syncing ${pendingMessages.length} pending messages`);
    242        
     226
    243227        // Send each message
    244228        for (const message of pendingMessages) {
     
    249233                    body: message.body
    250234                });
    251                
     235
    252236                if (response.ok) {
    253237                    await removePendingMessage(message.id);
    254                     console.log('Service Worker: Message synced successfully', message.id);
    255                 } else {
    256                     console.error('Service Worker: Failed to sync message', message.id, response.status);
    257238                }
    258239            } catch (error) {
    259                 console.error('Service Worker: Error syncing message', message.id, error);
    260             }
    261         }
    262        
     240                // Error syncing message
     241            }
     242        }
     243
    263244        // Notify clients about sync completion
    264245        const clients = await self.clients.matchAll();
     
    269250            });
    270251        });
    271        
     252
    272253    } catch (error) {
    273254        console.error('Service Worker: Background sync failed', error);
     
    279260 */
    280261self.addEventListener('push', (event) => {
    281     console.log('Service Worker: Push notification received');
    282    
    283262    const options = {
    284263        body: 'You have a new message from AI Assistant',
     
    311290            }
    312291        } catch (error) {
    313             console.error('Service Worker: Error parsing push data', error);
     292            // Error parsing push data
    314293        }
    315294    }
     
    324303 */
    325304self.addEventListener('notificationclick', (event) => {
    326     console.log('Service Worker: Notification clicked', event.action);
    327    
    328305    event.notification.close();
    329306   
     
    383360        });
    384361    } catch (error) {
    385         console.error('Service Worker: Error getting pending messages', error);
    386362        return [];
    387363    }
     
    400376        });
    401377    } catch (error) {
    402         console.error('Service Worker: Error removing pending message', error);
     378        // Error removing pending message
    403379    }
    404380}
     
    426402           
    427403        default:
    428             console.log('Service Worker: Unknown message type', type);
     404            // Unknown message type
    429405    }
    430406});
     
    437413        const cache = await caches.open(CACHE_NAME);
    438414        await cache.addAll(urls);
    439         console.log('Service Worker: URLs cached successfully', urls);
    440     } catch (error) {
    441         console.error('Service Worker: Error caching URLs', error);
     415    } catch (error) {
     416        // Error caching URLs
    442417    }
    443418}
     
    452427            cacheNames.map(cacheName => caches.delete(cacheName))
    453428        );
    454         console.log('Service Worker: All caches cleared');
    455     } catch (error) {
    456         console.error('Service Worker: Error clearing caches', error);
     429    } catch (error) {
     430        // Error clearing caches
    457431    }
    458432}
     
    475449                            if (age > MAX_AGE) {
    476450                                cache.delete(request);
    477                                 console.log('Service Worker: Deleted old cached response', request.url);
    478451                            }
    479452                        }
     
    492465 */
    493466self.addEventListener('online', () => {
    494     console.log('Service Worker: Connection restored');
    495467    // Trigger background sync when connection is restored
    496468    self.registration.sync.register('background-message-sync');
     
    498470
    499471self.addEventListener('offline', () => {
    500     console.log('Service Worker: Connection lost');
    501 });
    502 
    503 console.log('Service Worker: Script loaded successfully');
     472    // Connection lost
     473});
  • convertybot/trunk/assets/js/tracking.js

    r3437100 r3445725  
    1010    // Check if tracking config exists
    1111    if (typeof convertyBotTracking === 'undefined') {
    12         console.log('[ConvertyBot Tracking] Config not available, skipping basic tracking');
    1312        return;
    1413    }
     
    2524            this.initialized = true;
    2625
    27             console.log('[ConvertyBot Tracking] Initializing basic tracking...');
    28 
    2926            // Get session ID from cookie or storage
    3027            this.sessionId = this.getSessionId();
    3128
    3229            if (!this.sessionId) {
    33                 console.log('[ConvertyBot Tracking] No session ID found, waiting for chatbot to initialize');
    3430                // Listen for chatbot session
    3531                $(document).on('convertybot_session_started', function(e, data) {
     
    4743            this.setupClickTracking();
    4844            this.setupTimeTracking();
    49 
    50             console.log('[ConvertyBot Tracking] Basic tracking initialized', {
    51                 sessionId: this.sessionId,
    52                 pageType: convertyBotTracking.currentPage?.type
    53             });
    5445        },
    5546
     
    206197                url: convertyBotTracking.ajaxUrl,
    207198                type: 'POST',
    208                 data: data,
    209                 success: function(response) {
    210                     if (response.success) {
    211                         console.log('[ConvertyBot Tracking] ' + action + ' tracked successfully');
    212                     }
    213                 },
    214                 error: function(xhr, status, error) {
    215                     console.warn('[ConvertyBot Tracking] Failed to track ' + action, error);
    216                 }
     199                data: data
    217200            });
    218201        }
  • convertybot/trunk/convertybot.php

    r3445596 r3445725  
    33 * Plugin Name: ConvertyBot
    44 * Description: An intelligent AI-powered sales assistant for WooCommerce that helps visitors discover products, provides personalized recommendations, and generates dynamic discount codes to boost sales.
    5  * Version: 1.0.21
     5 * Version: 1.0.28
    66 * Author: ConvertyBot, 2wstechnologies Team
    77 * Author URI: https://convertybot.com
     
    4242
    4343// Define plugin constants
    44 define('CONVERTYBOT_VERSION', '1.0.26');
     44define('CONVERTYBOT_VERSION', '1.0.28');
    4545define('CONVERTYBOT_PLUGIN_URL', plugin_dir_url(__FILE__));
    4646define('CONVERTYBOT_PLUGIN_PATH', plugin_dir_path(__FILE__));
  • convertybot/trunk/readme.txt

    r3445596 r3445725  
    66Tested up to: 6.9
    77Requires PHP: 7.2
    8 Stable tag: 1.0.26
     8Stable tag: 1.0.28
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    249249== Changelog ==
    250250
     251= 1.0.28 =
     252* FIXED: Insight badges showing empty in visitor journeys timeline ({{this}} template replacement bug)
     253* FIXED: Simple variable replacement was overwriting {{this}} placeholder before #each loop could process it
     254
     255= 1.0.27 =
     256* FIXED: Empty yellow insight badges in visitor journeys timeline
     257* ADDED: Debug logging for insights data to diagnose data issues
     258* ADDED: Extra cleanup to remove empty timeline-insights divs
     259* IMPROVED: Better filtering of non-string and empty insights
     260
    251261= 1.0.26 =
    252262* FIXED: Chat window not closing when minimize button clicked
     
    360370== Upgrade Notice ==
    361371
     372= 1.0.28 =
     373Fix for empty insight badges - The {{this}} template placeholder in visitor journey timelines was being replaced with empty string before the #each loop could process it. Insights now display correctly.
     374
     375= 1.0.27 =
     376Debug update - Added logging to diagnose empty insight badges in visitor journeys. Check browser console for insights data.
     377
    362378= 1.0.26 =
    363379Critical fix - Chat window can now be properly closed/minimized. Also fixes mobile font sizes and avatar positioning.
Note: See TracChangeset for help on using the changeset viewer.