Analytics: 3-tab layout + fix geographic data loss; v1.1.34
Splits the analytics panel into Traffic / Engagement / System tabs so episode plays, engagement metrics, and contact/study data are no longer buried under the visitor log. Fixes a bug where topCountries, topStates, topCities, device breakdown, and referrers were computed from only the 100 most-recent visitor rows instead of all rows in the selected range — causing older geographic data (e.g. visits from India, Texas, Georgia) to silently disappear from the aggregate totals. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -253,6 +253,10 @@ export function register(app) {
|
||||
const botReasons = Object.entries(state.hitStats.botReasons ?? {})
|
||||
.sort((a, b) => b[1] - a[1]).slice(0, 10).map(([reason, count]) => ({ reason, count }))
|
||||
|
||||
// All range rows used for geographic/device/referrer aggregates — no cap so no visits are invisible
|
||||
const allRangeRows = rangeVisitorRows
|
||||
|
||||
// Capped to 100 for the visitor log display (with page history hydrated)
|
||||
const recentVisitorRows = rangeVisitorRows.slice(0, 100).map(row => {
|
||||
const fullVisitor = state.visitorStats.visitors[row.visitorId]
|
||||
return { ...row, pageHistory: fullVisitor?.pageHistory ?? [] }
|
||||
@@ -315,13 +319,13 @@ export function register(app) {
|
||||
returningVisits: state.visitorStats.returningVisits,
|
||||
firstVisitAt: state.visitorStats.firstVisitAt,
|
||||
lastVisitAt: state.visitorStats.lastVisitAt,
|
||||
topCountries: buildTopLocations(recentVisitorRows, 'country'),
|
||||
topStates: buildTopLocations(recentVisitorRows, 'state'),
|
||||
topCounties: buildTopLocations(recentVisitorRows, 'county'),
|
||||
topCities: buildTopLocations(recentVisitorRows, 'city'),
|
||||
topCountries: buildTopLocations(allRangeRows, 'country'),
|
||||
topStates: buildTopLocations(allRangeRows, 'state'),
|
||||
topCounties: buildTopLocations(allRangeRows, 'county'),
|
||||
topCities: buildTopLocations(allRangeRows, 'city'),
|
||||
deviceBreakdown: (() => {
|
||||
const counts = { mobile: 0, desktop: 0, tablet: 0, unknown: 0 }
|
||||
for (const row of recentVisitorRows) {
|
||||
for (const row of allRangeRows) {
|
||||
const d = row.device ?? 'unknown'
|
||||
counts[d] = (counts[d] ?? 0) + 1
|
||||
}
|
||||
@@ -329,7 +333,7 @@ export function register(app) {
|
||||
})(),
|
||||
topReferrers: (() => {
|
||||
const counts = {}
|
||||
for (const row of recentVisitorRows) {
|
||||
for (const row of allRangeRows) {
|
||||
if (!row.referrer) continue
|
||||
counts[row.referrer] = (counts[row.referrer] ?? 0) + 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user