Customer Segmentation Dashboard

Customer Segmentation Dashboard

Key Segmentation Indicators

Customer Segments Overview

Segmentation Insights

No insights generated yet. Please configure your data.

Customer Segmentation Dashboard Report

Key Segmentation Indicators

Customer Segments Overview

Segmentation Insights

No specific insights generated. Ensure your segments have valid customer counts and average values.

'; } } segmentationInsights.innerHTML = insightsHtml; } // --- Event Handlers (Globally accessible for onclick attributes) --- /** * Switches between dashboard and data configuration tabs. * @param {string} tabName - 'dashboard' or 'dataConfig'. */ window.switchTab = function(tabName) { // Guard clauses for elements if (!dashboardTabBtn || !dataConfigTabBtn || !dashboardTabContent || !dataConfigTabContent || !prevTabBtn || !nextTabBtn) { console.error("One or more tab elements not found."); return; } currentTab = tabName; // Update button styles dashboardTabBtn.classList.remove('active'); dataConfigTabBtn.classList.remove('active'); dashboardTabContent.classList.add('hidden'); dataConfigTabContent.classList.add('hidden'); if (tabName === 'dashboard') { dashboardTabBtn.classList.add('active'); dashboardTabContent.classList.remove('hidden'); prevTabBtn.disabled = true; nextTabBtn.disabled = false; renderKpiMetrics(); // Re-render dashboard KPI content renderSegmentsOverview(); // Re-render segments overview generateSegmentationInsights(); // Re-generate insights } else if (tabName === 'dataConfig') { dataConfigTabBtn.classList.add('active'); dataConfigTabContent.classList.remove('hidden'); prevTabBtn.disabled = false; nextTabBtn.disabled = true; renderAllSegmentInputRows(); // Re-render input rows when tab is active } }; /** * Navigates between tabs using 'Next' and 'Previous' buttons. * @param {string} direction - 'prev' or 'next'. */ window.navigateTabs = function(direction) { if (direction === 'next') { if (currentTab === 'dashboard') { switchTab('dataConfig'); } } else if (direction === 'prev') { if (currentTab === 'dataConfig') { switchTab('dashboard'); } } }; /** * Adds a new empty segment row to the data configuration. */ if (addSegmentBtn) { // Null check for addSegmentBtn addSegmentBtn.onclick = function() { const newSegmentId = generateUniqueId(); const newSegment = { id: newSegmentId, name: '', customers: null, avgValue: null, characteristics: '' }; customerSegments.push(newSegment); renderSegmentInputRow(newSegment); showMessage('New segment row added.', 'info'); }; } /** * Updates a specific property of a segment in the customerSegments array. * This function is called directly from input fields' oninput. * @param {string} id - The ID of the segment to update. * @param {string} property - The property to update ('name', 'customers', 'avgValue', 'characteristics'). * @param {*} value - The new value for the property. */ window.updateSegmentValue = function(id, property, value) { const segmentIndex = customerSegments.findIndex(s => s.id === id); if (segmentIndex !== -1) { customerSegments[segmentIndex][property] = value; } }; /** * Removes a segment from the customerSegments array and its corresponding input row. * @param {string} id - The ID of the segment to remove. */ window.removeSegment = function(id) { customerSegments = customerSegments.filter(s => s.id !== id); const segmentRow = document.getElementById(`segment-row-${id}`); if (segmentRow) { segmentRow.remove(); showMessage('Segment removed successfully.', 'success'); } else { console.warn(`Segment row with ID ${id} not found for removal.`); } }; /** * Saves the data (which is already updated via oninput) and refreshes the dashboard. */ if (saveDataBtn) { // Null check for saveDataBtn saveDataBtn.onclick = function() { // Filter out any segments that are completely empty or invalid customerSegments = customerSegments.filter(segment => segment.name.trim() !== '' || (typeof segment.customers === 'number' && !isNaN(segment.customers)) || (typeof segment.avgValue === 'number' && !isNaN(segment.avgValue)) ); // Ensure numerical values are indeed numbers customerSegments.forEach(segment => { segment.customers = parseFloat(segment.customers) || 0; segment.avgValue = parseFloat(segment.avgValue) || 0; }); renderKpiMetrics(); // Re-render dashboard KPIs renderSegmentsOverview(); // Re-render segments overview generateSegmentationInsights(); // Re-generate insights showMessage('Data saved and dashboard updated!', 'success'); }; } /** * Handles the PDF download functionality. */ if (downloadPdfBtn) { // Null check for downloadPdfBtn downloadPdfBtn.onclick = async function() { if (!pdfContent || !pdfKpiMetrics || !pdfSegmentsOverview || !pdfSegmentationInsights) { console.error("PDF content elements not found."); showMessage('Error: PDF content elements missing.', 'error'); return; } // Populate the hidden PDF content div with current dashboard data // KPI Metrics for PDF pdfKpiMetrics.innerHTML = `

Key Segmentation Indicators

`; const totalCustomers = customerSegments.reduce((sum, seg) => sum + (seg.customers || 0), 0); const numberOfSegments = customerSegments.length; const totalValue = customerSegments.reduce((sum, seg) => sum + ((seg.customers || 0) * (seg.avgValue || 0)), 0); const overallAvgValue = totalCustomers > 0 ? (totalValue / totalCustomers) : 0; const highValueCustomers = customerSegments.filter(seg => seg.avgValue > 500).reduce((sum, seg) => sum + (seg.customers || 0), 0); const percentHighValue = totalCustomers > 0 ? (highValueCustomers / totalCustomers) * 100 : 0; pdfKpiMetrics.innerHTML += `

Total Customers: ${totalCustomers.toLocaleString()}

Number of Segments: ${numberOfSegments}

Overall Average Customer Value: ${formatValue(overallAvgValue, '$')}

High-Value Customers (%): ${percentHighValue.toFixed(2)}%

`; // Segments Overview for PDF pdfSegmentsOverview.innerHTML = `

Customer Segments Overview

`; if (customerSegments.length === 0) { pdfSegmentsOverview.innerHTML += '

No segments defined for the overview.

'; } else { customerSegments.forEach(segment => { pdfSegmentsOverview.innerHTML += `

${segment.name || 'Unnamed Segment'}

Customers Average Value Characteristics
${(segment.customers || 0).toLocaleString()} ${formatValue(segment.avgValue, '$')} ${segment.characteristics || 'N/A'}
`; }); } // Segmentation Insights for PDF pdfSegmentationInsights.innerHTML = `

Segmentation Insights

`; let insightsForPdf = ''; if (customerSegments.length === 0) { insightsForPdf = '

No insights generated. Please configure your data.

'; } else { const sortedByValue = [...customerSegments].sort((a, b) => (b.avgValue || 0) - (a.avgValue || 0)); const sortedByCustomers = [...customerSegments].sort((a, b) => (b.customers || 0) - (a.customers || 0)); const highestValueSegment = sortedByValue[0]; const largestSegment = sortedByCustomers[0]; insightsForPdf += `
`; if (highestValueSegment) { insightsForPdf += `

The ${highestValueSegment.name} segment has the highest average customer value of ${formatValue(highestValueSegment.avgValue, '$')}.

`; } if (largestSegment && (highestValueSegment ? largestSegment.id !== highestValueSegment.id : true)) { insightsForPdf += `

The ${largestSegment.name} segment is currently the largest with ${largestSegment.customers.toLocaleString()} customers.

`; } const lowValueSegments = customerSegments.filter(seg => seg.avgValue < 200); if (lowValueSegments.length > 0) { insightsForPdf += `

Opportunity for Growth: Segments with lower average values (e.g., ${lowValueSegments.map(s => s.name).join(', ')}) could benefit from upselling or engagement strategies.

`; } const smallHighValueSegments = customerSegments.filter(seg => seg.avgValue >= 500 && seg.customers < 10000); if (smallHighValueSegments.length > 0) { insightsForPdf += `

Targeted Expansion: Segments like ${smallHighValueSegments.map(s => s.name).join(', ')} show high value but are relatively small. Focused acquisition campaigns could yield significant returns.

`; } insightsForPdf += `
`; } pdfSegmentationInsights.innerHTML += insightsForPdf; // Show the hidden content temporarily for html2canvas to render it pdfContent.style.display = 'block'; showMessage('Generating PDF...', 'info'); try { const canvas = await html2canvas(pdfContent, { scale: 2, // Increase scale for better quality useCORS: true, // If you have external images, enable CORS logging: false // Disable console logging from html2canvas }); const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF('p', 'mm', 'a4'); // 'p' for portrait, 'mm' for millimeters, 'a4' size const imgWidth = 210; // A4 width in mm const pageHeight = 297; // A4 height in mm const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 0; pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; while (heightLeft >= 0) { position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } pdf.save('Customer_Segmentation_Dashboard.pdf'); showMessage('PDF downloaded successfully!', 'success'); } catch (error) { console.error("Error generating PDF:", error); showMessage('Error generating PDF. Please try again.', 'error'); } finally { // Hide the content again after PDF generation pdfContent.style.display = 'none'; } }; } // --- Initial Load --- switchTab('dashboard'); // Start on the dashboard tab renderAllSegmentInputRows(); // Render initial data in config tab renderKpiMetrics(); // Render initial data in dashboard tab renderSegmentsOverview(); // Render initial segments overview generateSegmentationInsights(); // Generate initial insights });
Scroll to Top