Customer Segmentation Dashboard
Key Segmentation Indicators
Customer Segments Overview
Segmentation Insights
No insights generated yet. Please configure your data.
Data Configuration
Define your customer segments, their size, and average value. Click 'Add Segment' to add more rows.
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)}%
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
`; 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 += `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 += `