Dashboard: add trend arrows (▲/▼/●) with color to Website stats — compares day-over-day + update-to-update
This commit is contained in:
+18
-1
@@ -1,9 +1,26 @@
|
||||
{
|
||||
"period": "2026-06-09 to 2026-06-10",
|
||||
"updated": "2026-06-11 08:30",
|
||||
"updated": "2026-06-11 08:59",
|
||||
"visitors": 9,
|
||||
"visitors_trend": {
|
||||
"dir": "same",
|
||||
"change": "+0",
|
||||
"pct": "+0%"
|
||||
},
|
||||
"visitors_change": "",
|
||||
"latest_day": "2026-06-10",
|
||||
"latest_day_visitors": 5,
|
||||
"dod_trend": {
|
||||
"dir": "up",
|
||||
"change": "+1",
|
||||
"pct": "+25%"
|
||||
},
|
||||
"pageviews": 37,
|
||||
"pageviews_trend": {
|
||||
"dir": "same",
|
||||
"change": "+0",
|
||||
"pct": "+0%"
|
||||
},
|
||||
"pageviews_change": "",
|
||||
"bounce_rate": "\u2014",
|
||||
"bounce_rate_change": "",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"date": "Wednesday, June 10, 2026",
|
||||
"updated": "2026-06-11T08:30:10-04:00",
|
||||
"updated": "2026-06-11T08:59:40-04:00",
|
||||
"goals": [
|
||||
{
|
||||
"current": 1,
|
||||
@@ -111,5 +111,5 @@
|
||||
"Email capture (newsletter signup or lead magnet) needed before 10K/mo path is realistic."
|
||||
],
|
||||
"day": 3,
|
||||
"notes": "Day 3 auto-update at 08:30 UTC"
|
||||
"notes": "Day 3 auto-update at 08:59 UTC"
|
||||
}
|
||||
+23
-4
@@ -1062,17 +1062,31 @@
|
||||
period: '—',
|
||||
updated: '',
|
||||
visitors: 0,
|
||||
visitors_trend: {dir: 'same', change: '', pct: ''},
|
||||
pageviews: 0,
|
||||
pageviews_trend: {dir: 'same', change: '', pct: ''},
|
||||
latest_day: '',
|
||||
latest_day_visitors: 0,
|
||||
dod_trend: {dir: 'same', change: '', pct: ''},
|
||||
bounce_rate: '—',
|
||||
visit_duration: '—',
|
||||
top_referrers: [{source: 'Direct', visitors: 0}],
|
||||
countries: [],
|
||||
events: [],
|
||||
visitors_by_day: []
|
||||
visitors_by_day: [],
|
||||
agents_sold: 0
|
||||
};
|
||||
|
||||
let websiteStats = { ...defaultStats };
|
||||
|
||||
function trendArrow(t) {
|
||||
if (!t || t.dir === 'same') return '<span style="color:var(--text-muted);font-size:12px">●</span>';
|
||||
if (t.dir === 'new') return '<span style="color:var(--accent);font-size:12px" title="New">●</span>';
|
||||
const arrow = t.dir === 'up' ? '▲' : '▼';
|
||||
const color = t.dir === 'up' ? 'var(--success)' : 'var(--danger)';
|
||||
return `<span style="color:${color};font-size:11px">${arrow} ${t.pct}</span>`;
|
||||
}
|
||||
|
||||
function renderWebsite() {
|
||||
const s = websiteStats;
|
||||
const overview = document.getElementById('stats-overview');
|
||||
@@ -1084,18 +1098,23 @@
|
||||
<div class="stat-overview-card">
|
||||
<div class="stat-val">${s.visitors}</div>
|
||||
<div class="stat-lbl">Unique Visitors</div>
|
||||
<div class="stat-sub">${s.period}</div>
|
||||
<div class="stat-sub">${trendArrow(s.visitors_trend)} ${s.period}</div>
|
||||
</div>
|
||||
<div class="stat-overview-card">
|
||||
<div class="stat-val">${s.pageviews}</div>
|
||||
<div class="stat-lbl">Pageviews</div>
|
||||
<div class="stat-sub">${s.pageviews_per_visitor || (s.visitors > 0 ? (s.pageviews / s.visitors).toFixed(1) : '—')} avg</div>
|
||||
<div class="stat-sub">${trendArrow(s.pageviews_trend)} ${s.pageviews_per_visitor || (s.visitors > 0 ? (s.pageviews / s.visitors).toFixed(1) : '—')} avg</div>
|
||||
</div>
|
||||
<div class="stat-overview-card">
|
||||
<div class="stat-val">${s.agents_sold || 2}</div>
|
||||
<div class="stat-lbl">Agents Sold</div>
|
||||
<div class="stat-sub">via Stripe</div>
|
||||
</div>
|
||||
<div class="stat-overview-card">
|
||||
<div class="stat-val">${s.latest_day_visitors}</div>
|
||||
<div class="stat-lbl">${s.latest_day || 'Latest Day'}</div>
|
||||
<div class="stat-sub">${trendArrow(s.dod_trend)} vs prev day</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1122,7 +1141,7 @@
|
||||
|
||||
// Events card
|
||||
let eventRows = (s.events && s.events.length)
|
||||
? s.events.map(e => `<div class="stat-row-item"><span class="stat-name">${e.name}</span><span class="stat-num">${e.total} <span style="color:var(--text-muted);font-size:10px">(${e.unique})</span></span></div>`).join('')
|
||||
? s.events.map(e => `<div class="stat-row-item"><span class="stat-name">${e.name}</span><span class="stat-num">${e.total} <span style="color:var(--text-muted);font-size:10px">(${e.unique} uniq)</span></span></div>`).join('')
|
||||
: '<div class="stat-row-item" style="color:var(--text-muted);font-size:11px">No event data yet</div>';
|
||||
html += `<div class="stats-events-card">
|
||||
<h3>Custom Events</h3>
|
||||
|
||||
Reference in New Issue
Block a user