Analytics Plugin
Built-in event tracking and request monitoring for SonicJS. Store custom events, query them via API, and view request metrics in the admin dashboard.
Overview
The Analytics plugin is included with SonicJS core and enabled by default. It provides two complementary capabilities:
Custom Event Tracking
Track named events via HTTP API β single or batch. Stored in the document repository and queryable by event name, category, user, session, or date range.
Request Monitoring Dashboard
Admin dashboard at /admin/analytics showing last-24h request totals, unique IPs, average response time, error count, top URLs, and recent activity β sourced from system_logs.
Not currently implemented: automatic page view recording, session duration / bounce rate calculation, real-time active-user counts, reports UI, data export, and per-plugin configuration options.
Custom Events
Event Structure
Events are stored as analytics_event documents in the document repository. The fields you can track and filter on:
TrackEventInput
interface TrackEventInput {
event: string // required β event name
category?: string // default: 'user-activity'
properties?: Record<string, unknown> // arbitrary metadata
userId?: string
sessionId?: string
path?: string
// ipAddress and userAgent are captured automatically from the request
}
Queryable Fields
| Field | Indexed column | Notes |
|---|---|---|
event | q_evt_event | Exact match |
category | q_evt_category | Exact match |
userId | q_evt_user_id | Exact match |
sessionId | q_evt_session_id | Exact match |
path | q_evt_path | Exact match |
API Reference
Track Event
No authentication required to write events.
Track a single event.
Request Body:
event(required) β event name stringcategoryβ event category (default:user-activity)propertiesβ optional metadata objectpathβ page URL pathsessionIdβ session identifieruserIdβ user identifier (overridden by authenticated user if logged in)
Track Single Event
curl -X POST 'https://your-app.workers.dev/api/events' \
-H 'Content-Type: application/json' \
-d '{
"event": "button_click",
"category": "ui",
"properties": { "button": "signup", "variant": "hero" },
"path": "/pricing"
}'
Response
{
"success": true,
"eventId": "doc_abc123"
}
Track Batch Events
Send an array of up to 100 events in one request. Each event follows the same shape as a single event. Events are written sequentially β not in a single DB transaction.
Batch Track
curl -X POST 'https://your-app.workers.dev/api/events' \
-H 'Content-Type: application/json' \
-d '[
{ "event": "page_view", "path": "/home" },
{ "event": "page_view", "path": "/about" },
{ "event": "click", "category": "nav", "properties": { "target": "pricing" } }
]'
Response
{
"success": true,
"eventIds": ["doc_abc", "doc_def", "doc_ghi"],
"count": 3
}
Query Events
Admin auth required.
Query Parameters:
eventβ filter by event namecategoryβ filter by categoryuserIdβ filter by user IDsessionIdβ filter by session IDstartDateβ Unix timestamp (seconds)endDateβ Unix timestamp (seconds)limitβ max results (default:50)offsetβ pagination offset (default:0)
Query Events
curl -X GET 'https://your-app.workers.dev/api/events?category=ui&limit=50' \
-H 'Authorization: Bearer YOUR_TOKEN'
Response
{
"events": [
{
"id": "doc_abc123",
"createdAt": 1700000000,
"event": "button_click",
"category": "ui",
"path": "/pricing"
}
],
"total": 142
}
Event Stats
Admin auth required.
Returns total event count, unique user count, unique session count, and top 20 events by frequency.
Query Parameters:
startDateβ Unix timestamp (seconds)endDateβ Unix timestamp (seconds)
Event Stats
curl -X GET 'https://your-app.workers.dev/api/events/stats' \
-H 'Authorization: Bearer YOUR_TOKEN'
Response
{
"totalEvents": 5420,
"uniqueUsers": 312,
"uniqueSessions": 891,
"topEvents": [
{ "event": "page_view", "count": 3100 },
{ "event": "button_click", "count": 980 }
]
}
Admin Dashboard
Path: /admin/analytics β requires admin role.
Displays last-24-hour metrics sourced from the system_logs table:
| Metric | Source |
|---|---|
| Total Requests | COUNT(*) where category = 'api' |
| Unique Visitors | COUNT(DISTINCT ip_address) where category = 'api' |
| Avg Response Time | AVG(duration) where category = 'api' |
| Errors | COUNT(*) where level IN ('error', 'fatal') |
| Top Pages | Top 10 URLs by request count |
| Recent Activity | Last 20 API requests |
Note: The dashboard reads from system_logs, not the analytics_event documents stored by POST /api/events. If system_logs is empty or doesn't exist yet, all metrics show zero β this is expected on a fresh install.
There are no sub-pages for reports, real-time monitoring, or settings. The only admin analytics URL is /admin/analytics.
Hooks Integration
The plugin registers four hooks at boot:
| Hook | Priority | What it does |
|---|---|---|
request:start | 1 | Generates an in-memory session ID (data.analytics.sessionId). Not persisted to DB. |
request:end | 1 | Logs request duration to console.debug. No DB write. |
user:login | 8 | Attempts to call context.services?.analyticsService?.trackEvent(...). Currently a no-op β analyticsService is not registered in the service context. |
content:view | 8 | Same as user:login β no-op until analyticsService is wired up. |
To track login or content-view events today, use POST /api/events directly from your handler instead of relying on hooks.
Data Storage
Events tracked via POST /api/events are stored as documents of type analytics_event in the unified documents table β not in separate analytics_pageviews or analytics_events tables (those don't exist).
Five generated columns index the queryable fields:
| Generated column | Maps to |
|---|---|
q_evt_event | json_extract(data, '$.event') |
q_evt_category | json_extract(data, '$.category') |
q_evt_user_id | json_extract(data, '$.userId') |
q_evt_session_id | json_extract(data, '$.sessionId') |
q_evt_path | json_extract(data, '$.path') |
Each event is stored as a published document (is_published = 1, maxVersionsPerRoot = 1) under tenant default.