SEO Technical Health Check Dashboard
Audit Report for as of
Overall Health Score
0
Category Performance
Crawl & Indexing
On-Page SEO
Site Speed
Detailed Findings
Audit Data Input
Enter data from your SEO audit tools to generate the health check dashboard.
Audit Metrics
Error: Could not load required libraries. The tool cannot function.
'; return; } Chart.register(ChartDataLabels); let gaugeInstances = {}; const TABS = ['healthDashboardTab', 'auditDataInputTab']; let currentTabIndex = 0; const sampleData = { url: 'my-usa-ecommerce.com', totalPages: 5280, indexablePages: 5150, missingTitles: 45, missingMetas: 120, lcp: 2.8, inp: 210, cls: 0.16 }; function initialize() { document.getElementById('input-url').value = sampleData.url; document.getElementById('input-date').valueAsDate = new Date(); document.getElementById('input-total-pages').value = sampleData.totalPages; document.getElementById('input-indexable-pages').value = sampleData.indexablePages; document.getElementById('input-missing-titles').value = sampleData.missingTitles; document.getElementById('input-missing-metas').value = sampleData.missingMetas; document.getElementById('input-lcp').value = sampleData.lcp; document.getElementById('input-inp').value = sampleData.inp; document.getElementById('input-cls').value = sampleData.cls; tech_seo_processData(); tech_seo_updateNavButtons(); } function getScoreColor(score) { if (score >= 90) return { bg: '#d1e7dd', text: '#0f5132', name: 'Excellent' }; if (score >= 70) return { bg: '#d4edda', text: '#198754', name: 'Good' }; if (score >= 50) return { bg: '#fff3cd', text: '#664d03', name: 'Needs Improvement' }; return { bg: '#f8d7da', text: '#842029', name: 'Poor' }; } function createGauge(canvasId, score) { const ctx = document.getElementById(canvasId); if (!ctx) return; if (gaugeInstances[canvasId]) gaugeInstances[canvasId].destroy(); const color = getScoreColor(score).text; gaugeInstances[canvasId] = new Chart(ctx, { type: 'doughnut', data: { datasets: [{ data: [score, 100 - score], backgroundColor: [color, '#e9ecef'], borderColor: '#fff', borderWidth: 2, circumference: 180, rotation: -90, }] }, options: { responsive: true, maintainAspectRatio: false, cutout: '65%', plugins: { tooltip: { enabled: false }, datalabels: { formatter: (value, context) => context.dataIndex === 0 ? score + '%' : '', color: '#1c3d5a', font: { size: 24, weight: 'bold' } } } } }); } function calculateScores(data) { const scores = {}; const totalPages = data.totalPages > 0 ? data.totalPages : 1; // Crawl & Indexing Score const indexRatio = (data.indexablePages / totalPages) * 100; scores.crawl = Math.max(0, Math.min(100, indexRatio)); // On-Page Score const titleErrorRate = (data.missingTitles / totalPages) * 100; const metaErrorRate = (data.missingMetas / totalPages) * 100; const avgErrorRate = (titleErrorRate + metaErrorRate) / 2; scores.onpage = Math.max(0, 100 - avgErrorRate); // Site Speed Score const lcpScore = data.lcp <= 2.5 ? 100 : data.lcp <= 4 ? 50 : 10; const inpScore = data.inp <= 200 ? 100 : data.inp <= 500 ? 50 : 10; const clsScore = data.cls <= 0.1 ? 100 : data.cls <= 0.25 ? 50 : 10; scores.speed = (lcpScore + inpScore + clsScore) / 3; // Overall Score (weighted) scores.overall = (scores.crawl * 0.4) + (scores.onpage * 0.3) + (scores.speed * 0.3); return { crawl: Math.round(scores.crawl), onpage: Math.round(scores.onpage), speed: Math.round(scores.speed), overall: Math.round(scores.overall) }; } window.tech_seo_processData = function() { const inputData = { url: document.getElementById('input-url').value, date: new Date(document.getElementById('input-date').value).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }), totalPages: parseInt(document.getElementById('input-total-pages').value) || 0, indexablePages: parseInt(document.getElementById('input-indexable-pages').value) || 0, missingTitles: parseInt(document.getElementById('input-missing-titles').value) || 0, missingMetas: parseInt(document.getElementById('input-missing-metas').value) || 0, lcp: parseFloat(document.getElementById('input-lcp').value) || 0, inp: parseInt(document.getElementById('input-inp').value) || 0, cls: parseFloat(document.getElementById('input-cls').value) || 0 }; const scores = calculateScores(inputData); updateDashboardUI(inputData, scores); tech_seo_changeTab('healthDashboardTab'); } function updateDashboardUI(data, scores) { document.getElementById('audited-url-display').textContent = data.url; document.getElementById('audit-date-display').textContent = data.date; const overallScoreEl = document.getElementById('overall-score-circle'); const overallScoreColor = getScoreColor(scores.overall); overallScoreEl.textContent = scores.overall; overallScoreEl.style.backgroundColor = overallScoreColor.text; document.getElementById('overall-score-text').textContent = `Your site's technical health is rated: ${overallScoreColor.name}`; createGauge('crawl-gauge', scores.crawl); createGauge('onpage-gauge', scores.onpage); createGauge('speed-gauge', scores.speed); updateFindingsList(data); } function updateFindingsList(data) { const findings = []; const totalPages = data.totalPages > 0 ? data.totalPages : 1; // Indexability const indexRate = (data.indexablePages / totalPages); let status = indexRate >= 0.95 ? 'good' : indexRate >= 0.8 ? 'warn' : 'bad'; findings.push({status, text: `${data.indexablePages.toLocaleString()} of ${data.totalPages.toLocaleString()} pages (${(indexRate*100).toFixed(1)}%) are indexable.`}); // On-Page status = data.missingTitles === 0 ? 'good' : (data.missingTitles / totalPages) < 0.05 ? 'warn' : 'bad'; findings.push({status, text: `${data.missingTitles.toLocaleString()} pages have missing title tags.`}); status = data.missingMetas === 0 ? 'good' : (data.missingMetas / totalPages) < 0.1 ? 'warn' : 'bad'; findings.push({status, text: `${data.missingMetas.toLocaleString()} pages have missing meta descriptions.`}); // Speed status = data.lcp <= 2.5 ? 'good' : data.lcp <= 4 ? 'warn' : 'bad'; findings.push({status, text: `LCP is ${data.lcp}s.`}); status = data.inp <= 200 ? 'good' : data.inp <= 500 ? 'warn' : 'bad'; findings.push({status, text: `INP is ${data.inp}ms.`}); status = data.cls <= 0.1 ? 'good' : data.cls <= 0.25 ? 'warn' : 'bad'; findings.push({status, text: `CLS is ${data.cls}.`}); const listEl = document.getElementById('findings-list'); listEl.innerHTML = ''; findings.forEach(item => { const iconMap = { good: '✓', warn: '!', bad: '✗' }; listEl.innerHTML += `