Customer Journey Analysis Dashboard
Overall Journey Summary
Total Journey Records
0
Overall Conversion Rate
0%
Avg. Time to Convert (Days)
0
Total Revenue Impact ($)
$0
Conversion Rate by Stage
Average Time in Stage (Days)
Journey Status Distribution
Detailed Customer Journey Records
| ID | Customer Name | Journey Name | Current Stage | Start Date | Last Activity | Conversion Status | Conversion Date | Revenue Impact ($) |
|---|
Add/Edit Journey Records
Manage Existing Records
| ID | Customer Name | Journey Name | Current Stage | Start Date | Last Activity | Conversion Status | Conversion Date | Revenue Impact ($) | Actions |
|---|
No data to display.
'; return; } // Sort data by value descending for general charts, custom for specific types let sortedData = Object.entries(data); if (valueType === 'percentage') { // For conversion rate by stage, sort by stage order const stageOrder = ["Awareness", "Consideration", "Decision", "Purchase", "Retention", "Advocacy"]; sortedData.sort(([labelA], [labelB]) => stageOrder.indexOf(labelA) - stageOrder.indexOf(labelB)); } else if (valueType === 'days') { // For average time in stage, sort by stage order const stageOrder = ["Awareness", "Consideration", "Decision", "Purchase", "Retention", "Advocacy"]; sortedData.sort(([labelA], [labelB]) => stageOrder.indexOf(labelA) - stageOrder.indexOf(labelB)); } else if (valueType === 'status') { const statusOrder = ["Converted", "In Progress", "Abandoned"]; sortedData.sort(([labelA], [labelB]) => statusOrder.indexOf(labelA) - statusOrder.indexOf(labelB)); } else { sortedData.sort(([, valA], [, valB]) => valB - valA); } // Determine the maximum value for scaling bars const maxValue = Math.max(...Object.values(data), 1); // Avoid division by zero if all values are 0 sortedData.forEach(([label, value]) => { const barWidth = (value / maxValue) * 100; // Scale based on max value for visual representation const percentageOfTotal = totalValue > 0 ? ((value / totalValue) * 100).toFixed(1) : 0; let displayValue; let barClass = 'bg-blue-300'; // Default bar color if (valueType === 'percentage') { displayValue = `${value.toFixed(1)}%`; } else if (valueType === 'days') { displayValue = `${value.toFixed(0)} Days`; } else if (valueType === 'status') { displayValue = `${value} Records`; if (label === 'Converted') barClass = 'status-converted'; else if (label === 'In Progress') barClass = 'status-in-progress'; else if (label === 'Abandoned') barClass = 'status-abandoned'; } else { // 'count' displayValue = `${value} Records`; } const barWrapper = document.createElement('div'); barWrapper.classList.add('chart-bar-wrapper'); barWrapper.innerHTML = ` ${label}:
${displayValue} (${percentageOfTotal}%)
`;
targetElement.appendChild(barWrapper);
});
}
/**
* Calculates and renders all distribution charts.
*/
function renderDistributionCharts() {
const totalJourneys = customerJourneyRecords.length;
// Conversion Rate by Stage
const stageConversionCounts = {};
const stageTotalCounts = {};
const stageOrder = ["Awareness", "Consideration", "Decision", "Purchase", "Retention", "Advocacy"];
stageOrder.forEach(stage => {
stageConversionCounts[stage] = 0;
stageTotalCounts[stage] = 0;
});
customerJourneyRecords.forEach(record => {
stageTotalCounts[record.currentStage] = (stageTotalCounts[record.currentStage] || 0) + 1;
if (record.conversionStatus === 'Converted') {
stageConversionCounts[record.currentStage] = (stageConversionCounts[record.currentStage] || 0) + 1;
}
});
const conversionRatesByStage = {};
stageOrder.forEach(stage => {
if (stageTotalCounts[stage] > 0) {
conversionRatesByStage[stage] = (stageConversionCounts[stage] / stageTotalCounts[stage]) * 100;
} else {
conversionRatesByStage[stage] = 0;
}
});
renderBarChart(conversionRateByStageChartElem, conversionRatesByStage, 'percentage');
// Average Time in Stage (Days)
const timeInStageSums = {};
const timeInStageCounts = {};
stageOrder.forEach(stage => {
timeInStageSums[stage] = 0;
timeInStageCounts[stage] = 0;
});
customerJourneyRecords.forEach(record => {
const daysInStage = calculateDaysBetween(record.startDate, record.lastActivityDate);
timeInStageSums[record.currentStage] = (timeInStageSums[record.currentStage] || 0) + daysInStage;
timeInStageCounts[record.currentStage] = (timeInStageCounts[record.currentStage] || 0) + 1;
});
const avgTimeInStage = {};
stageOrder.forEach(stage => {
if (timeInStageCounts[stage] > 0) {
avgTimeInStage[stage] = timeInStageSums[stage] / timeInStageCounts[stage];
} else {
avgTimeInStage[stage] = 0;
}
});
renderBarChart(avgTimeInStageChartElem, avgTimeInStage, 'days');
// Journey Status Distribution
const journeyStatusCounts = customerJourneyRecords.reduce((acc, record) => {
acc[record.conversionStatus] = (acc[record.conversionStatus] || 0) + 1;
return acc;
}, {});
renderBarChart(journeyStatusDistributionChartElem, journeyStatusCounts, 'status');
}
/**
* Generates a PDF of the dashboard content.
* Excludes non-essential UI elements like buttons and input forms.
*/
function generatePdf() {
// Create a temporary div to hold only the content for PDF
const pdfContentWrapper = document.createElement('div');
pdfContentWrapper.classList.add('pdf-content-wrapper'); // Apply PDF-specific styles
// Add title
const title = document.createElement('h2');
title.textContent = 'Customer Journey Analysis Report';
title.classList.add('text-2xl', 'font-bold', 'mb-4');
pdfContentWrapper.appendChild(title);
// Add summary cards
const summarySection = document.createElement('div');
summarySection.classList.add('grid', 'grid-cols-4', 'gap-4', 'mb-6');
summarySection.innerHTML = `
Total Journey Records
${totalJourneysCountElem.textContent}
Overall Conversion Rate
${overallConversionRateElem.textContent}
Avg. Time to Convert (Days)
${avgTimeToConvertElem.textContent}
Total Revenue Impact ($)
${totalRevenueImpactElem.textContent}
Conversion Rate by Stage
Average Time in Stage (Days)
Journey Status Distribution
Detailed Customer Journey Records
| ID | Customer Name | Journey Name | Current Stage | Start Date | Last Activity | Conversion Status | Conversion Date | Revenue Impact ($) |
|---|
