Growth analytics for Buffer, built on the official
@bufferapp/cli. One command turns your
posting history into a shareable insight report — narrative highlights, a best-time-to-post
heatmap, weekly trend, and channel comparison.
Zero dependencies. Read-only. Unofficial — not affiliated with Buffer.
Buffer's new public API exposes post metrics (aggregatedPostMetrics, per-post Post.metrics),
but it's an aggregate-only, experimental surface: no trend intervals, no per-channel breakdown,
no ranking. This tool fills the analysis gap client-side and renders the result as a
single self-contained HTML file — made to be read by the marketer on your team,
not just the engineer who ran the command.
- Narrative first. The report opens with plain sentences — your best posting window, your strongest channel, the quarter's direction — then shows the evidence.
- "What to try next." Deterministic, rule-based suggestions where every hint names the numbers behind it. No LLM, no black box.
- Emailable. One HTML file, inline everything, no JS, works offline, prints cleanly, respects dark mode.
# prerequisite: the official Buffer CLI, authenticated
npm i -g @bufferapp/cli && buffer init
npx buffer-growth-kit report --open # last 90 days
npx buffer-growth-kit report --from 2026-04-01 --to 2026-06-30 --out q2.htmlNo Buffer account yet? See the output with sample data:
npx buffer-growth-kit report --demo --openEverything goes through the official CLI (buffer aggregatedPostMetrics, buffer posts list,
buffer channels list) — auth, schema, and validation stay upstream. This tool only:
- Splits your range into weekly windows and issues one aggregate call per window
(serially, honoring
Retry-After) to build the trend the API can't return in one call. - Caches immutable windows forever. Buffer ingests metrics once daily, so any window
ending >48h ago can never change — re-runs are nearly free on rate limits
(cache:
~/.buffer-growth-kit/cache.json). - Buckets every sent post by weekday × 2-hour slot in your account timezone to build the heatmap. Posts from the last 48h are excluded — their metrics aren't final.
- Derives hints with plain rules (best slot uplift ≥15% → timing hint; busiest channel trailing on engagement rate → post less, invest more; small channel out-performing → double down). Each hint carries its evidence.
Found while building this against the experimental metrics API:
- No
intervalparameter onaggregatedPostMetrics— trends require N windowed calls, which the 15m/24h/30d stacked rate limits then penalize. - No
groupBy: channel— cross-network aggregation only returns metrics every channel supports, so per-channel comparison is one call per channel. topPostsis referenced in the CLI's metrics docs but absent frombuffer schema list— ranking requires paginatingposts listand sorting client-side.- Rate-limit state is stderr-only — a structured
meta.rateLimitfield on stdout JSON is documented as planned; it would remove the need to parse warnings.
- v1.1 — UTM auto-tagging + GA4 join. Buffer metrics end at the click; conversion lives in
your web analytics. The bridge is disciplined UTM tagging at
posts createtime and a join on the other side. That's where engagement data becomes revenue data. - CSV export of the normalized dataset.
- Engagement rate is shown only where the network reports it — never recomputed with a homemade formula. "—" means the network doesn't expose that metric.
- Metrics lag up to ~24h (Buffer ingests daily); the report footer shows freshness.
- Single organization per run (
--org <id>to pick one).
npm test # node --test, no network needed
npm run demo # regenerate the sample reportMIT
