03

CLI Tracking

Track how developers use your CLI tool. See which commands are popular, how long they take, and what errors occur -- without collecting PII.

Install
npm install @bettermeter/node
Auto-track with Commander.js
import { BetterMeter } from "@bettermeter/node";
import { Command } from "commander";

const bm = new BetterMeter({
  siteId: "my-cli-tool",
  apiKey: "bm_...",
});

const program = new Command();

// Wraps all commands — tracks name, flags, exit code
bm.wrapCommander(program, { version: "1.0.0" });

program.command("deploy").action(() => { /* ... */ });
program.parse();

// Flush on exit
process.on("SIGTERM", () => bm.shutdown());
Manual tracking
bm.trackCommand({
  command: "deploy",
  subcommand: "preview",
  flags: ["--prod", "--verbose"],
  version: "2.1.0",
  durationMs: 4500,
  exitCode: 0,
  isCi: !!process.env.CI,
});

What gets tracked

Command names and flag names only. Flag values, arguments, and file paths are never sent. The SDK captures OS and architecture for environment analytics.

07

CLI Reference

The BetterMeter CLI lets you query analytics from the terminal with beautiful visual output. All commands accept -r/--range and --json, and every one but all-sites also accepts -s/--site — that one is account-wide and takes no site. -l/--limit applies only to the commands that return a ranked list.

Install & authenticate
npm install -g bettermeter
bettermeter login -t <apiKey> -u https://bettermeter.com

Output Formats

By default, the CLI renders rich visual output with ASCII art charts, colored text, sparklines, and box-drawn stat cards. All output uses Unicode characters compatible with every modern terminal. Colors auto-detect terminal capabilities and respect the NO_COLOR environment variable.

Default (visual)Line charts, bar charts, sparklines, styled tables with color
--jsonRaw JSON data -- ideal for scripting, piping to jq, or programmatic use

Visual output includes:

  • Line charts for timeseries data (daily visitors, invocations)
  • Horizontal bar charts for ranked lists (pages, sources, countries)
  • Sparklines inline with overview stats for quick trend visualization
  • Box-drawn stat cards with colored change indicators for overviews
  • Styled tables with box-drawing borders for detailed data
Example: visual vs JSON
# Visual output (default)
bettermeter stats -s example.com

# JSON output for scripting
bettermeter stats -s example.com --json | jq '.visitors'

Authentication

login -t <key> -u <url>Authenticate with API key and dashboard URL
logoutRemove stored credentials
whoamiShow current authenticated user

Real-Time

live -s <siteId> [--activity] [--cursor <cursor>] [--json]Live visitor count, or add --activity for the recent human event feed and --cursor for incremental polling (--json for raw output)
live:screen -s <siteId> [--json]Print the authenticated Big Screen URL for the rewindable live visitor display and its 30-minute activity timeline (--json for structured output)

Portfolio

all-sites [-r <range>] [--json]Traffic for every site you can access, side by side: visitors, pageviews, sessions and custom events per site, each site's period-over-period visitor change, and the account-wide totals. Takes no -s/--site

Web Analytics

Human-traffic commands exclude known bots, explicit headless automation, and high-confidence scraper cohorts by default. Add --include-bots to stats, pages, sources, timeseries, AI traffic, countries, devices, browsers, sessions, session-stats, channels, goals, goal:show, or goals:suggest to include them.

-l/--limit is accepted by the commands that return a ranked list: pages, sources, bots, countries, browsers, visitors, sessions, events, campaigns, conversions, keywords, campaign:visitors, export, cli-commands, mcp-tools, mcp-clients, and api-endpoints. It has no default of its own: omit it and the command returns the endpoint's own default page, which differs per dataset — today visitors returns 50 rows where pages returns 10 — and the flag is how you ask for a specific number. The summary, trend, and detail commands do not accept it — stats, ai-traffic, timeseries, devices, channels, marketing, ads, campaign, event, and the cli, mcp, and api overview and timeseries commands. On sources --filter and bots --category the limit is applied before the filter, so a filtered result can hold fewer rows than the limit.

statsOverview: visitors, pageviews, sessions + % change, or a new-baseline state when the previous period is empty
pagesTop pages by visitor count
sourcesTraffic sources (--filter all|ai|traditional)
ai-trafficAI referral breakdown by platform
botsBot/crawler traffic (--category all|ai-crawler|search|monitoring|scraper)
timeseriesDaily visitor/pageview trend
countriesVisitors by country
devicesDevice breakdown
browsersBrowser breakdown
visitorsPeople with their event source (web / CLI / MCP / API / bot) and its detail, plus first-touch source, campaign, repeat visits, and lifecycle
sessionsEvery session with duration, pages, events, entry to exit path, engagement tier, and bounce, under period totals
visitor <visitorId>One person's profile, first touch, sessions, and event timeline
visitor:update <visitorId>Set an opaque user ID, display name, or visitor/customer lifecycle status
visitor:properties <visitorId>List the key/value properties stored on a visitor
visitor:tag <visitorId>Set or remove arbitrary key/value properties on a visitor
visitor:findFind a visitor by email, CRM contact id, or exact property key/value
eventsCustom events with counts
event <name>One custom event in depth: total fires, unique visitors, property value breakdown, recent fires
campaignsAutomatically captured campaign URL attribution (UTM + click IDs)
campaign <name>Detailed campaign report (quality, variants, breakdowns)
campaign:visitors <name>Everyone one campaign brought in: who clicked, the page they landed on, their variant, device and country, and what they did afterwards
keywordsKeywords driving traffic (utm_term, with visit quality)
marketingFull marketing report: campaigns, landing pages, channel mix
screenshot <path>Capture one landing page and save it as an image (--site, optional --output)
channelsChannel breakdown (Direct, Paid Search, Organic, etc.)
exportFull report (--format json|csv|md)

CLI Analytics

cli-overviewInvocations, callers, success rate, avg duration
cli-commandsTop commands by invocation count
cli-timeseriesDaily CLI activity

MCP Analytics

mcp-overviewInvocations, callers, success rate, avg duration
mcp-toolsTop MCP tools by invocation count
mcp-clientsClient breakdown (Claude, Cursor, etc.)
mcp-timeseriesDaily MCP activity

API Analytics

api-overviewInvocations, callers, error rate, avg duration
api-endpointsTop endpoints by invocation count
api-timeseriesDaily API activity

Builder

dashboardsList saved custom dashboard layouts shown in the dashboard left nav
dashboard:createCreate a custom dashboard layout, including the Editor/Admin-only paidPerformance Meta widget
dashboard:update -i <id>Update a custom dashboard layout (only the flags you pass change)
dashboard:deleteDelete a custom dashboard layout
reportsList saved report templates
report:createCreate a report template, including the Editor/Admin-only paidMedia section
report:previewPreview a report with live Meta delivery when paidMedia is enabled
report:update -i <id>Update a report template (only the flags you pass change)
report:deleteDelete a report template

Pulse AI

pulse askAsk Pulse anything — including linked visitor journeys behind recent conversions
pulse threadsList your saved Pulse conversations for a site
adsMeta spend and link clicks compared with compatible tracked campaign traffic
ad-creativeThe ad behind a visit, or every ad in a campaign; --utm-content resolves one exact creative
ads:syncPull ad spend from connected ad accounts now
conversionsCRM records carrying one of our ad click IDs, with matched, unmatched and awaiting-upload counts (--won for closed only)
ad-connections -s <siteId>Connected ad accounts for a site and their sync health
crmConnected CRMs for a site and their sync health
crm:syncPull CRM conversions now instead of waiting for the next scheduled sync (--full to re-read everything)
slackSlack channels wired to this site's Pulse alerts, with delivery health
slack:connectConnect a Slack Incoming Webhook; a test message is posted before it is stored
slack:testPost to a connected channel now, to prove the webhook still works
slack:updateEnable, disable, rename or re-threshold a connected channel
slack:removeDisconnect a Slack channel; alerts already recorded are kept
pulse threadReplay one Pulse conversation as a transcript
pulse thread-deleteDelete a Pulse conversation
pulse insightsAnomalies, trends, milestones, and campaign, channel, geography, conversion and engagement shifts
pulse healthProduct health score (0-100, grade A-F)
pulse briefingDaily/weekly briefing (-p/--period daily|weekly)
pulse forecastTraffic forecast (-m/--metric, -d/--days)
pulse compareCompare two periods (-r/--range, --from2, --to2)
pulse alertsList monitoring alert rules
pulse alerts:createCreate alert (-t/--type, -n/--name, -c/--condition)
pulse alerts:deleteDelete an alert (-i/--id)
pulse notificationsRecent notifications (--unread for unread only)

Search Rankings and AI Visibility

brand-report <domain>Generate search rankings report (-q/--queries)
brand-config <domain>View/update brand monitoring config
brand-compare <domain>Compare rankings vs competitors (-q, -c)
brand-alerts <domain>Manage ranking alerts (-a list|create|delete|enable|disable)
ai-mentions <domain>AI chatbot brand mentions (-q/--queries, -p/--providers)
ai-mentions:history [domain]Stored AI mention scans, newest first — reads history, never runs a paid scan
backlinks <domain>Backlink profile: domain rank, referring domains

Paid external scans accept 1-10 queries per request. Competitor comparison accepts up to 10 competitors.

Conversion Goals

goals -s <siteId> [--include-bots]List human conversion goals, stable converters, rates, and momentum
goal:show -s <siteId> -g <goalId> [--include-bots]Compare current/prior evolution, first-touch acquisition, exposed-visitor efficiency, and momentum
goal:create -s <siteId> -n <name>Create a conversion goal (pageview URL, custom event, outbound link, or download)
goal:update -s <siteId> -g <goalId>Update a conversion goal — rename, retarget, revalue or archive it
goal:delete -s <siteId> -g <goalId>Delete a conversion goal
goals:suggest -s <siteId> [--include-bots]Analyze human traffic and suggest high-value conversion targets with rationales

Site Management

sites listList all sites
sites add <domain>Add a new site — sign in to the dashboard; an API key cannot create sites
sites remove <siteId>Remove a site — sign in to the dashboard; an API key cannot delete sites
sites info <siteId>Show site details and tracking snippet
sites update <siteId> --currency <code>Set the display currency (ISO 4217 code, defaults to CAD)
install <siteId>Get tracker snippet for a site

Team Management

members list -s <siteId>List site members
members add <email>Add a member (-s, -r viewer|editor|admin, --all-sites)
members remove <id>Remove a member (-s)
invitation:cancel <id>Cancel a pending invitation (-s), before it is accepted
members update-role <id>Update member role (-s, -r)

Billing

billingShow current plan, usage, and billing info (--json)

Options

-s, --siterequired except all-sites
string
Site ID (domain). Every command requires it except all-sites, which covers every site you can access
-r, --range
string
Date range: today, 7d, 30d, 90d, 12m. Presets include exactly the labeled number of calendar dates. Default: 30d
-l, --limit
number
Max results, on list commands only. No default — omit it and the endpoint's own page size applies
--json
flag
Output raw JSON instead of visual charts and tables