Zero-dependency Go client for the Plausible Stats API v2 (
/api/v2/query
). Typed queries, friendly helpers, and tidy responses.
- Features
- Install
- Quick start
- API overview
- Live example (optional)
- Example output
- Contact & projects
- Use cases
- License
- One endpoint, many shapes: Aggregate, Timeseries, Breakdown, and a small Realtime helper-all via
POST /api/v2/query
. - Typed request/response models with helpers (
MetricInt
,MetricFloat
,MetricRevenue
). - Query builders:
NewAggregate
,NewTimeseries
,NewBreakdown
. - Options:
WithFilters
,WithOrder
,WithTimeLabels
,WithImports
,WithTotalRows
,WithPagination
,WithDimensions
. - Zero dependencies (stdlib only).
- Unit tests with
httptest.Server
. - Usage examples in code comments and
examples_test.go
.
go get github.com/dragstor/go-plausible
Import:
import "github.com/dragstor/go-plausible"
client := plausible.NewClient("YOUR-API-KEY", nil) // nil => http.DefaultClient
q := plausible.NewAggregate(
"example.com",
[]string{"visitors", "pageviews"},
plausible.Preset("30d"),
)
resp, err := client.Query(ctx, q)
if err != nil { /* handle */ }
for _, row := range resp.Results {
v, _ := row.MetricInt(0) // visitors
p, _ := row.MetricInt(1) // pageviews
_ = v; _ = p
}
Tiny mental model:
flowchart LR
A[Your App] -->|Query| B[go-plausible Client]
B -->|POST /api/v2/query| C[Plausible API v2]
C -->|results + meta + query| B --> A
q := plausible.NewAggregate("example.com",
[]string{"visitors", "pageviews"},
plausible.Preset("7d"),
)
resp, _ := client.Query(ctx, q)
q := plausible.NewTimeseries("example.com",
[]string{"visitors"},
plausible.Preset("7d"),
"time:day",
plausible.WithTimeLabels(),
)
resp, _ := client.Query(ctx, q)
q := plausible.NewBreakdown("example.com",
[]string{"pageviews"},
plausible.Preset("30d"),
[]string{"event:page"},
plausible.WithOrder("pageviews", "desc"),
plausible.WithPagination(100, 0),
)
resp, _ := client.Query(ctx, q)
q := plausible.NewBreakdown("example.com",
[]string{"visitors"},
plausible.Preset("month"),
[]string{"visit:country_name"},
plausible.WithFilters(
plausible.Is("visit:country_name", "Serbia", "Germany"),
plausible.Contains("event:page", "/pricing"),
plausible.HasDone("event:goal", "Signup"), // behavioral filter
),
plausible.WithTotalRows(),
)
resp, _ := client.Query(ctx, q)
Date ranges
plausible.Preset("7d") // "7d", "month", "all", etc.
plausible.Range(startTime, endTime) // RFC3339 timestamps
plausible.DayRange("2025-09-01", "2025-09-30")
Realtime helper
current, _ := client.RealtimeVisitors(ctx, "example.com") // last 5 minutes
If you want to run against the real API, provide two env vars:
export PLAUSIBLE_API_KEY=your-api-key
export PLAUSIBLE_TEST_SITE=example.com
Then run your own snippet (see Quick start) or wire a tiny cmd/live-query
of your choice.
Tip: prefer shell env first; only fall back to a local .env
if you use one.
Screenshot (out.png
) from a sample run:
Plain text:
== Aggregate (last 7 days) ==
Aggregate: got 1 row(s)
Aggregate metrics:
- visitors: 208
- pageviews: 278
== Realtime (last 5 minutes) ==
Current visitors: 0
== Timeseries (daily, last 7 days) ==
Timeseries: 7 data points
2025-09-21: 12 visitors
2025-09-22: 11 visitors
2025-09-23: 29 visitors
2025-09-24: 19 visitors
2025-09-25: 35 visitors
2025-09-26: 39 visitors
2025-09-27: 64 visitors
== Custom range (last hour) ==
Custom range results:
Range: 2025-09-28T20:39:50Z to 2025-09-28T21:39:50Z
Rows:
Row 1
- visitors: 1
All examples finished.
Maintainer
Nikola Stojković
🦋 Bluesky: https://bsky.app/profile/brka.io · ✖️ X: https://x.com/IT_mafija
Not affiliated with Plausible.
I also build HostedStatus.page — uptime monitoring, incident management, and public status pages: https://hostedstatus.page
- 🐙 gocaptcha — Invisible + behavioral CAPTCHA for Go
net/http
apps.
GitHub: https://github.com/dragstor/gocaptcha - 🐙 ginsitemap — A simple
sitemap.xml
middleware forgin-gonic
.
GitHub: https://github.com/dragstor/ginsitemap - 🎩📸 shottr-alfred-workflow — Alfred workflow for the Shottr screenshot & annotation app on macOS.
GitHub: https://github.com/dragstor/shottr-alfred-workflow · Shottr: https://shottr.cc · Alfred: https://www.alfredapp.com
This library is intentionally small and zero-dependency, so it fits into many developer workflows. Common use cases include:
- Embedded site dashboards - fetch aggregates or timeseries and render them in a web dashboard. For example, you can back an "Open Startup" page using
NewAggregate
orNewTimeseries
to drive widgets that show visitors, pageviews, etc. - Integrating with Go web frameworks - call the client from HTTP handlers in frameworks like Gin (https://github.com/gin-gonic/gin), Chi (https://github.com/go-chi/chi), or Echo (https://github.com/labstack/echo) to expose metrics on pages or APIs.
- Background jobs and cron tasks - use the client from scheduled workers to fetch stats, persist snapshots, or send alerts when thresholds are crossed.
- Command-line tools and scripts - build small CLI utilities that query Plausible.io and print reports (CSV/JSON) or feed other tools.
- Serverless functions and workers - the zero-dependency design keeps binary size small for serverless deployments (AWS Lambda, Cloud Run, etc.).
- Testing and CI - because the test suite uses
httptest.Server
, it's straightforward to mock responses in unit tests or CI pipelines.
Because this client focuses on the Stats API v2 POST /api/v2/query
endpoint, it works well for dashboards, automation, and embedded site displays where typed, reproducible query results are required.
MIT - see LICENSE.