Snapshot Metrics
Track what exists in your product (counts, states, totals) using scheduled group calls. Complements event tracking for a complete picture of account health.
Events track what users do. Snapshot metrics track what exists. Together, they give you a complete picture of account health and product engagement.
The problem with deriving counts from events
It is tempting to calculate totals from events: count Project_Created events, subtract Project_Deleted events, and derive the current number of projects. In practice, this breaks down:
- Missed events: A network failure, a deploy without instrumentation, or a bulk import that bypasses your tracking code means lost events.
- Drift over time: Small inaccuracies compound. After months, your derived count can diverge significantly from reality.
- Historical imports: Data that existed before you started tracking has no corresponding creation events.
- Bulk operations: An admin deleting 50 projects in one action may not generate 50 individual events.
The reliable approach is to query your database for the truth and send that to Accoil directly.
How snapshot metrics work
The pattern is straightforward:
- A scheduled job runs at a regular interval (daily is typical)
- The job queries your database for current counts and states
- The job sends a group call with those values as traits
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Scheduler │ ──── │ Your DB │ ──── │ Accoil │
│ (cron/job) │ │ (source of │ │ group() call │
│ │ │ truth) │ │ with traits │
└─────────────┘ └──────────────┘ └─────────────────┘
runs daily queries sends countsBecause the values come directly from your database, they are always accurate regardless of whether events were tracked correctly.
Common snapshot metrics
| Trait | Description | Example value |
|---|---|---|
total_project_count | Total projects in the account | 47 |
active_user_count | Users active in the last 30 days | 12 |
integration_count | Connected third-party integrations | 3 |
total_document_count | Documents created in the account | 284 |
storage_used_mb | Storage consumed in megabytes | 1520 |
team_member_count | Total users on the account | 8 |
template_count | Custom templates created | 15 |
Choose metrics that reflect how deeply an account is using your product. Counts that grow with engagement are particularly valuable for health scoring.
Example: daily sync job
This example shows a Node.js scheduled job that queries your database and sends snapshot metrics to Accoil for each account.
const API_BASE = "https://in.accoil.com";
const API_KEY = process.env.ACCOIL_API_KEY;
async function sendGroup(payload) {
const response = await fetch(`${API_BASE}/v2/group`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${API_KEY}`,
},
body: JSON.stringify(payload),
});
return response.status; // 202 Accepted
}
// Run this on a daily schedule (cron, cloud scheduler, etc.)
async function dailySnapshotSync() {
// Query your database for all active accounts
const accounts = await db.query(`
SELECT
a.id,
a.name,
a.status,
a.plan,
a.mrr_cents,
(SELECT COUNT(*) FROM projects WHERE account_id = a.id) AS project_count,
(SELECT COUNT(*) FROM users
WHERE account_id = a.id
AND last_active_at > NOW() - INTERVAL '30 days') AS active_user_count,
(SELECT COUNT(*) FROM integrations WHERE account_id = a.id) AS integration_count,
(SELECT COUNT(*) FROM users WHERE account_id = a.id) AS team_member_count
FROM accounts a
WHERE a.status != 'deleted'
`);
const now = new Date().toISOString();
for (const account of accounts) {
await sendGroup({
groupId: String(account.id),
traits: {
name: account.name,
status: account.status,
plan: account.plan,
mrr: account.mrr_cents,
total_project_count: account.project_count,
active_user_count: account.active_user_count,
integration_count: account.integration_count,
team_member_count: account.team_member_count,
last_snapshot_at: now,
},
timestamp: now,
});
}
console.log(`Snapshot sync complete: ${accounts.length} accounts updated`);
}Key implementation details
- Run daily. Once per day is sufficient for most metrics. Running more frequently increases load without adding analytical value.
- Query the database directly. The source of truth is your database, not your event stream.
- Include
last_snapshot_at. This trait lets you verify in Accoil that the sync is running and how recently each account was updated. - Send all relevant traits together. Each group call can include both snapshot metrics and standard account traits (name, status, plan, mrr).
- Convert IDs to strings. The
groupIdfield expects a string. If your database uses integer IDs, convert them withString(account.id).
Snapshot metrics vs. event tracking
| Aspect | Event tracking (track call) | Snapshot metrics (group call) |
|---|---|---|
| What it measures | Individual user actions | Current state of the account |
| When it fires | On user action, in real time | On a schedule (e.g., daily) |
| Source of truth | Client or server instrumentation | Database query |
| Example | Report_Created | total_report_count: 284 |
| Accuracy | Can miss events | Always accurate (queries DB) |
| Use case | Feature adoption, engagement patterns | Account health, usage depth, plan limits |
Both are essential. Events tell you what is happening. Snapshots tell you where things stand.
Best practices
- Run on a schedule, not on user action. Snapshot metrics should reflect the state of the world at a point in time, not react to individual events.
- Keep the job idempotent. If the job runs twice, the second run should produce the same result. Since group traits are overwritten on each call, this happens naturally.
- Monitor the job. Log completions and failures. Include
last_snapshot_atin the traits so you can detect stale data in Accoil. - Start with 3-5 metrics. Choose counts that best reflect account engagement depth. Add more as your analytics maturity grows.
- Use snapshot metrics for hierarchy too. If you use group hierarchy, you can send snapshot metrics at each level -- workspace-level counts, project-level counts, and account-level rollups.
Related
- Group Call -- the API call used to send snapshot metrics
- Group Hierarchy -- multi-level account structures
- How Accoil Works -- the three-call model overview