Smart Click-to-Sale Attribution Tracker

Smart Click-to-Sale Attribution Tracker

Analyze marketing channels by attributing sales back to the initial click.

Dashboard is Ready

Input your campaign data in the next tab and run the analysis to populate this dashboard.

Total Conversions

${totals.sales}

Avg Conv. Rate

${totals.convRate.toFixed(2)}%

Overall ROAS

${totals.roas.toFixed(2)}x

${tableRows}
ChannelClicksSalesConv. Rate RevenueCostCPAROAS
`; Object.values(charts).forEach(chart => chart.destroy()); charts.revenue = new Chart(document.getElementById('revenueChart'), { type: 'bar', data: { labels: channels, datasets: [{ label: 'Revenue', data: channels.map(c => analysis[c].revenue), backgroundColor: colors }] }, options: { plugins: { legend: { display: false } }, responsive: true, maintainAspectRatio: true } }); charts.conversions = new Chart(document.getElementById('conversionsChart'), { type: 'doughnut', data: { labels: channels, datasets: [{ label: 'Conversions', data: channels.map(c => analysis[c].sales), backgroundColor: colors }] }, options: { responsive: true, maintainAspectRatio: true } }); document.getElementById('download-pdf-btn').addEventListener('click', handlePdfDownload); lucide.createIcons(); } async function handlePdfDownload() { if (!lastResults) return; const { jsPDF } = window.jspdf; const { analysis } = lastResults; // Populate PDF container document.getElementById('pdf-generation-date').textContent = new Date().toLocaleDateString(); const totals = { clicks: Object.values(analysis).reduce((s, c) => s + c.clicks, 0), sales: Object.values(analysis).reduce((s, c) => s + c.sales, 0), revenue: Object.values(analysis).reduce((s, c) => s + c.revenue, 0), cost: Object.values(analysis).reduce((s, c) => s + c.cost, 0), }; totals.convRate = totals.clicks > 0 ? (totals.sales / totals.clicks) * 100 : 0; document.getElementById('pdf-summary').innerHTML = `
$${totals.revenue.toFixed(2)}
Total Revenue
${totals.sales}
Total Conversions
${totals.convRate.toFixed(2)}%
Avg. Conv. Rate
$${(totals.cost / totals.sales).toFixed(2)}
Avg. CPA
`; const tableHtml = ` ${Object.keys(analysis).map(channel => { const data = analysis[channel]; return ``}).join('')}
ChannelClicksSales RevenueCPAROAS
${channel}${data.clicks}${data.sales} $${data.revenue.toFixed(2)}$${data.cpa.toFixed(2)}${data.roas.toFixed(2)}x
`; document.getElementById('pdf-main-table').innerHTML = tableHtml; document.getElementById('pdf-chart-revenue').src = charts.revenue.toBase64Image(); document.getElementById('pdf-chart-conversions').src = charts.conversions.toBase64Image(); try { const canvas = await html2canvas(document.getElementById('pdf-content'), { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgProps = pdf.getImageProperties(imgData); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight); pdf.save('Marketing_Attribution_Report.pdf'); } catch (e) { console.error("PDF generation failed:", e); alert("An error occurred generating the PDF."); } } // --- Event Listeners --- tabs.forEach((tab, index) => tab.btn.addEventListener('click', () => switchTab(index))); prevBtn.addEventListener('click', () => switchTab(currentTab - 1)); nextBtn.addEventListener('click', () => switchTab(currentTab + 1)); analyzeBtn.addEventListener('click', handleAnalysis); // --- Initialization --- clickDataInput.value = sampleClickData; salesDataInput.value = sampleSalesData; costDataInput.value = sampleCostData; switchTab(0); updateNavButtons(); lucide.createIcons(); });
Scroll to Top