Headlessly
Analytics

Metric

Business measurements -- MRR, DAU, churn rate, NPS, and any quantifiable KPI derived from events or external sources.

Schema

import { Noun } from 'digital-objects'

export const Metric = Noun('Metric', {
  name: 'string!',
  value: 'number!',
  type: 'Counter | Gauge | Histogram | Summary',
  unit: 'string',
  dimensions: 'string',
  organization: '-> Organization',
  timestamp: 'datetime',
  record: 'Recorded',
  reset: 'Reset',
  snapshot: 'Snapshotted',
})

Fields

FieldTypeRequiredDescription
namestringYesMetric name (e.g. mrr, dau, churn_rate, nps)
valuenumberYesCurrent metric value
typeenumNoMetric type: Counter, Gauge, Histogram, or Summary
unitstringNoUnit of measurement (e.g. USD, users, percent, ms)
dimensionsstringNoDimension labels for slicing (e.g. plan:pro,region:us)
organization-> OrganizationNoTenant this metric belongs to
timestampdatetimeNoWhen this measurement was taken

Relationships

FieldDirectionTargetDescription
organization->OrganizationTenant this metric belongs to

Verbs

VerbEventDescription
createCreatedDefine a new metric
updateUpdatedUpdate metric fields
deleteDeletedRemove a metric
recordRecordedRecord a new value for this metric
resetResetReset the metric value to zero or baseline
snapshotSnapshottedCapture a point-in-time snapshot for historical tracking

Verb Lifecycle

import { Metric } from '@headlessly/analytics'

// BEFORE hook -- validate before recording
Metric.recording(metric => {
  if (metric.value < 0 && metric.type === 'Counter') {
    throw new Error('Counter metrics cannot have negative values')
  }
})

// Execute
await Metric.record('metric_k7TmPvQx')

// AFTER hook -- react to new recording
Metric.recorded(metric => {
  console.log(`${metric.name}: ${metric.value} ${metric.unit}`)
})

Metric Types

  • Counter: Monotonically increasing value. Total sign-ups, total revenue, total API calls. Only goes up (or resets to zero).
  • Gauge: Point-in-time measurement that can go up or down. Current MRR, active users, queue depth.
  • Histogram: Distribution of values in configurable buckets. API response times, deal sizes, session durations.
  • Summary: Statistical summary with quantiles. P50/P95/P99 latency, median deal value.

Cross-Domain Patterns

Metrics aggregate data from every corner of the system:

import { Subscription } from '@headlessly/billing'

// Update MRR metric when subscriptions change
Subscription.created((sub, $) => {
  const mrr = await $.Metric.find({ name: 'mrr' })
  if (mrr.length) {
    $.Metric.record(mrr[0].$id)
  }
})

Subscription.cancelled((sub, $) => {
  const churn = await $.Metric.find({ name: 'churn_rate' })
  if (churn.length) {
    $.Metric.record(churn[0].$id)
  }
})
  • Billing: MRR, ARR, churn rate, NRR, LTV derived from Stripe subscription and invoice data
  • CRM: Pipeline velocity, deal conversion rate, average deal value computed from CRM entities
  • Support: Average response time, resolution time, CSAT scores aggregated from tickets
  • Marketing: Campaign ROI, cost per lead, conversion rates computed from campaigns and leads
  • Goals: Goals reference metrics as their measurement source -- Goal.metric points to a Metric

Query Examples

SDK

import { Metric } from '@headlessly/analytics'

// Find all financial metrics
const financial = await Metric.find({
  name: { $in: ['mrr', 'arr', 'churn_rate', 'nrr', 'ltv'] },
})

// Get a specific metric
const mrr = await Metric.get('metric_k7TmPvQx')

// Create a new metric
await Metric.create({
  name: 'dau',
  value: 0,
  type: 'Gauge',
  unit: 'users',
})

// Record a new value
await Metric.record('metric_k7TmPvQx')

// Snapshot for historical tracking
await Metric.snapshot('metric_k7TmPvQx')

MCP

headless.ly/mcp#search
{
  "type": "Metric",
  "filter": { "type": "Gauge" },
  "sort": { "timestamp": "desc" },
  "limit": 20
}
headless.ly/mcp#fetch
{ "type": "Metric", "id": "metric_k7TmPvQx" }
headless.ly/mcp#do
const metrics = await $.Metric.find({ type: 'Gauge' })
await $.Metric.record('metric_k7TmPvQx')
await $.Metric.snapshot('metric_k7TmPvQx')

REST

# List metrics
curl https://analytics.headless.ly/~acme/metrics?type=Gauge

# Get a specific metric
curl https://analytics.headless.ly/~acme/metrics/metric_k7TmPvQx

# Create a metric
curl -X POST https://analytics.headless.ly/~acme/metrics \
  -H 'Content-Type: application/json' \
  -d '{"name": "dau", "value": 0, "type": "Gauge", "unit": "users"}'

# Record a new value
curl -X POST https://analytics.headless.ly/~acme/metrics/metric_k7TmPvQx/record

# Snapshot
curl -X POST https://analytics.headless.ly/~acme/metrics/metric_k7TmPvQx/snapshot

On this page