Developers Analytics & usage

Observe

Analytics & usage

Read Frontpage site analytics, plan meters, and the built page list from the CLI — with real response shapes.

What this covers

Three read-only observe commands share the RL-READ rate-limit class (see Rate limits):

  • frontpage analytics — traffic dashboard JSON (pageviews, visitors, top pages/sources)
  • frontpage usage — plan entitlements and AI / bandwidth / storage meters
  • frontpage pages — routes the site currently exposes (path + title)

Viewer role is enough. None of these publish or mutate the site branch.

Analytics

frontpage analytics
frontpage analytics --days 7
frontpage analytics --days 30 --site acme

# Structured ops (same cores as the editor agent tools)
frontpage analytics summary --days 30
frontpage analytics query --dimension path --measure count --limit 10
frontpage analytics funnel --steps '[{"path":"/"},{"path":"/pricing"}]' --days 14
frontpage analytics timeseries --metric pageviews --interval day --days 14
frontpage analytics compare --a '{"device":"mobile"}' --b '{"device":"desktop"}'
frontpage analytics sql --sql "SELECT path, count(*)::int AS n FROM analytics_events GROUP BY 1 ORDER BY n DESC LIMIT 10"

Bare analytics / analytics dashboard returns the legacy dashboard JSON (GET). Subcommands use POST with allowlisted dimensions/measures; SQL is guard-validated and RLS site-scoped. Without --json, the CLI prints the result object directly (pretty-printed JSON).

Typical dashboard shape (fields may grow; treat unknown keys as forward-compatible):

{
  "days": 7,
  "range": {
    "from": "2026-07-26T06:54:57.611Z",
    "to": "2026-08-02T06:54:57.611Z"
  },
  "totals": {
    "events": 3389,
    "pageviews": 526,
    "visitors": 313,
    "sessions": 396,
    "conversions": 0,
    "revenue": 0,
    "totalSeconds": 1694871,
    "avgScroll": 48
  },
  "deltas": {
    "visitors": -70.2,
    "sessions": -67.5,
    "pageviews": -70.1,
    "conversions": null,
    "revenue": null
  },
  "topPages": [
    { "path": "/", "views": 315 },
    { "path": "/pricing", "views": 67 }
  ],
  "topSources": [
    { "source": "direct", "sessions": 348 },
    { "source": "search", "sessions": 23 },
    { "source": "social", "sessions": 22 },
    { "source": "referral", "sessions": 19 },
    { "source": "paid", "sessions": 1 }
  ],
  "pages": [
    {
      "path": "/",
      "pageviews": 315,
      "visitors": 220,
      "sessions": 285,
      "avgSeconds": 3301,
      "avgScroll": 50
    }
  ]
}

--days

  • Default is 7 when omitted.
  • Pass an integer day window: --days 1, --days 30, etc.
  • range.from / range.to are ISO timestamps for the window that was queried.
  • deltas compare against the previous equal-length window (null when not applicable).

Analytics reflect Frontpage first-party tracking on the live/staging site surfaces. Empty or sparse sites return zeros — that is success, not an auth failure.

Usage (plan meters)

frontpage usage
frontpage usage --site acme

Prints plan entitlements and current-cycle meters. Useful when exit code 2 might mean AI budget rather than HTTP rate limiting.

{
  "plan": {
    "id": "pro",
    "label": "Pro",
    "customDomain": true,
    "extensions": true,
    "aiBudgetUsd": 50,
    "bandwidthGb": 100,
    "storageGb": 10,
    "timeMachineDays": 30
  },
  "ai": {
    "used": 12.4,
    "limit": 50,
    "pct": 0.248,
    "warn": false,
    "atLimit": false,
    "over": false
  },
  "bandwidth": {
    "used": 3.2,
    "limit": 100,
    "pct": 0.032,
    "warn": false,
    "atLimit": false,
    "over": false
  },
  "storage": {
    "used": 1.1,
    "limit": 10,
    "pct": 0.11,
    "warn": false,
    "atLimit": false,
    "over": false
  },
  "members": {
    "used": 2,
    "limit": 5,
    "pct": 0.4,
    "warn": false,
    "atLimit": false,
    "over": false
  },
  "cycleResetsAt": "2026-09-01T00:00:00.000Z"
}

Exact plan ids and limits depend on the site’s subscription. Internal/demo plans may show very large limits. Branch on ai.over / ai.atLimit (and the same flags on other meters) rather than hardcoding plan names.

Pages list

frontpage pages
frontpage pages --json
frontpage pages --site acme --json

Human mode prints path and title columns. JSON envelope:

{
  "ok": true,
  "command": "pages",
  "data": {
    "slug": "acme",
    "pages": [
      { "path": "/", "title": "Acme — Home" },
      { "path": "/pricing", "title": "Pricing" },
      { "path": "/about", "title": "About" }
    ]
  }
}

Use this before SEO edits or agent prompts so you target paths that actually exist. Titles come from the site’s page metadata / build, not from analytics.

Agent recipes

# Weekly traffic snapshot
frontpage analytics --days 7 > /tmp/fp-analytics.json

# Before prompting: confirm routes
frontpage pages --json

# Diagnose exit 2 after a failed prompt
frontpage usage
# if ai.atLimit / ai.over → budget; else see /developers/rate-limits

Related