https://github.com/andrerfcsantos/go-plausible
Plausible API wrapper for Go
https://github.com/andrerfcsantos/go-plausible
api-wrapper go golang plausible-analytics
Last synced: 4 months ago
JSON representation
Plausible API wrapper for Go
- Host: GitHub
- URL: https://github.com/andrerfcsantos/go-plausible
- Owner: andrerfcsantos
- License: mit
- Created: 2021-05-30T15:01:07.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2025-02-23T18:39:30.000Z (over 1 year ago)
- Last Synced: 2025-10-27T09:37:54.829Z (8 months ago)
- Topics: api-wrapper, go, golang, plausible-analytics
- Language: Go
- Homepage:
- Size: 93.8 KB
- Stars: 22
- Watchers: 1
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `go-plausible` - Go Wrapper for the Plausible API
[](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible) [](https://goreportcard.com/report/github.com/andrerfcsantos/go-plausible)
Go wrapper/client for the [Plausible](https://plausible.io/) API.
It currently supports the full API of Plausible, which includes:
* [Stats API](https://plausible.io/docs/stats-api)
* [Site Provisioning API](https://plausible.io/docs/sites-api)
## Table of Contents
* [Basic Usage](#basic-usage)
* [Concepts](#concepts)
* [Time Periods](#time-periods)
* [Properties](#properties)
* [Filters](#filters)
* [Metrics](#metrics)
* [Time Intervals](#metrics)
* [Queries (Stats API)](#queries)
* [Current Visitors](#currrent-visitors)
* [Aggregate Queries](#aggregate-queries)
* [Time series Queries](#timeseries-queries)
* [Breakdown Queries](#breakdown-queries)
* [Site Provisioning API](#site-provisioning-api)
* [List sites](#provisioning-api-get-sites)
* [Get site](#provisioning-api-get-site)
* [Get/Create Shared Links](#provisioning-api-shared-links)
* [Create new sites](#provisioning-api-create-new-sites)
* [Events API](#events-api)
* [Tests](#tests)
* [Unit Tests](#unit-tests)
* [Integration Tests](#integration-tests)
* [Integration Tests with provisioning API](#integration-tests-provisioning)
* [Bugs and Feedback](#bugs-feedback)
* [Contributing](#contributing)
* [License](#license)
```go
import "github.com/andrerfcsantos/go-plausible/plausible"
```
To use this client, you'll need an API token, which you can get from the Plausible Dashboard.
With the API token, create a client and get a handler for one or more sites:
```go
package main
import "github.com/andrerfcsantos/go-plausible/plausible"
func main() {
// Create a client with an API token
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
// You can reuse the same client to get handlers for additional sites
myothersite := client.Site("otherexample.com")
}
```
There a few concepts that are useful to know before using this wrapper or the Plausible API.
When requesting aggregate information to the API, it's only possible to get data for a given period of time. For
instance,
"the last 7 days", "the last month" or "the current day" are examples of time periods.
All time periods are relative to a date. When the date information is missing from a time period, the date is assumed to
be "today". It's also possible to specify a time period between two specific dates.
Time periods are represented in this library by
the [TimePeriod](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible#TimePeriod) type.
Unless you want low-level access to the API, you don't need to create a `TimePeriod` directly, and you can just use the
helper functions to build a time period:
```go
// Get the period for the last 6 months from today
p := plausible.Last6Months()
```
To associate a date to a time period, chain the result with `FromDate()` or
`OfDate()`:
```go
// Get the period for the last 12 months from the 1st of January 2021
p := plausible.Last12Months().FromDate(plausible.Date{Day:1, Month: 1, Year: 2021})
```
To make a custom period between 2 dates:
```go
// Get the period for the first 15 days of 2021
p := plausible.CustomPeriod(plausible.Date{Day:1, Month: 1, Year: 2021}, plausible.Date{Day:15, Month: 1, Year: 2021})
```
To know more about time periods, see [Plausible Docs: Time Periods](https://plausible.io/docs/stats-api#time-periods)
Each pageview or custom event has some properties associated with it. These properties can be used when querying the API
to filter the results.
Properties are represented in this library by
the [Property](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible#Property)
type. Properties have a name and value. The name of a property is represented by
the [PropertyName](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible#PropertyName)
type. Typically, most users won't need to make custom property names and can just use the constant `PropertyName`
values declared at the top-level of the package like `VisitOs` or `VisitBrowser`.
To make a custom `PropertyName`, the function `CustomPropertyName()` can be used:
```go
pName := plausible.CustomPropertyName("myevent")
```
Obtaining custom property names via this method is needed when you have custom events and want to refer to those events
as a property.
To easily make a custom property with a name and a value, you can use the `CustomProperty` function:
```go
p := plausible.CustomProperty("myevent", "myeventvalue")
```
To know more about properties, see [Plausible Docs: Properties](https://plausible.io/docs/stats-api#properties)
Filters allow drilling down and segment the data to which the results refer to. All queries for data accept an optional
filter argument.
In this library, filters are represented by
the [Filter](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible#Filter) type.
A filter consists of a simple list of properties by which you want to filter. For instance, to create a filter that
filters all visits by their operating system, you can do:
```go
f := plausible.NewFilter().ByVisitOs("Windows")
```
You can add more properties to the filter by chaining calls:
```go
f := plausible.NewFilter().ByVisitOs("Windows").ByVisitBrowser("Firefox")
```
This will filter the results based on the visits from Windows users that were using Firefox. So, a filter basically
consists of a logic AND of all its properties.
You can also instantiate a filter directly if you want a more low-level access to the API. For instance, this an
alternative way to write the filter above:
```go
f := plausible.Filter{
Properties: plausible.Properties{
{Name: plausible.VisitOs, Value: "Windows"},
{Name: plausible.VisitBrowser, Value: "Firefox"},
}
}
```
For each property, you can provide a set of values, separated by `|` to make the filter match any of the provided
values. For instance, to filter the data by visits of users using firefox in either linux or windows, we can do:
```go
f := plausible.NewFilter().ByVisitOs("Windows|Linux").ByVisitBrowser("Firefox")
```
To know more about properties, see [Plausible Docs: Filtering](https://plausible.io/docs/stats-api#filtering)
Metrics are aggregate information about the data. All queries have the option for you to choose the metrics you want to
see included in the results.
There are 6 metrics currently that you can ask the results for: number of visitors, number of page views, visit duration, bounce rate, visits and events.
In this library, these metrics are represented by
the [Metric](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible#Metric)
type. There are 6 constants of type `Metric`, each one representing one of the 6 metrics: `Visitors`,
`PageViews`, `BounceRate`, `VisitDuration`, `Events` and `Visits`
For instance, if for a query you only want information about the pageviews and number of visitors, you can pass this to
the query in the metrics parameter:
```go
metrics := plausible.Metrics {
plausible.Visitors,
plausible.PageViews,
},
```
For convenience, when you want to get information about all metrics, there's a function `AllMetrics()`
that returns all the 6 metrics. However, please note that not all queries support requests for all metrics. For that
reason, use requests for all metrics with caution. If you try to use a metric in a query that does not support that
metric, you will get an error message saying which property was at fault.
Time intervals are used for [time series queries](#timeseries-queries) to specify the interval of time between 2
consecutive data points.
A time interval is represented by
the [TimeInterval](https://pkg.go.dev/github.com/andrerfcsantos/go-plausible/plausible#TimeInterval) type. There are
currently 2 time intervals: date and month. This library also exposes two `TimeInterval`
constants for these value: `DateInterval` and `MonthInterval` respectively.
A `MonthInterval` means a month of difference between data points. For instance, if you ask for time series data over
the last 6 months with a month interval, this means you will get 6 data points back - 1 for each month.
A `DateInterval`, depending on the query, means a day or an hour of difference between each data point. For instance, if
you ask for time series data over the last 30 days with a date interval, you will get 30 data points back - 1 for each
day. However, with a `DateInterval`, when the period of the time series refers to a day, for instance "today", the data
points will actually have 1 hour of interval between them. You can check the `Date` string field of each data point to
know about which date/hour the data refers to.
There are 4 types of queries supported by the API:
* Current Visitors
* Aggregate Queries
* Timeseries Queries
* Breakdown Queries
This is the most straight forward query - for a given site return the number of current visitors:
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
visitors, err := mysite.CurrentVisitors()
if err != nil {
// handle error
}
fmt.Printf("Site %s has %d current visitors!\n", mysite.ID(), visitors)
}
```
An aggregate query reports data for metrics aggregated over a period of time.
A query like "the total number of visitors today" fall into this category, where the period is a day (in this case "
today") and the metric is the number of visitors.
Here's how to write this query:
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
// Build query
todaysVisitorsQuery := plausible.AggregateQuery{
Period: plausible.DayPeriod(),
Metrics: plausible.Metrics{
plausible.Visitors,
},
}
// Make query
result, err := mysite.Aggregate(todaysVisitorsQuery)
if err != nil {
// handle error
}
fmt.Printf("Total visitors of %s today: %d\n", mysite.ID(), result.Visitors)
}
```
A time series query reports a list of data points over a period of time, where each data point contains data about
metrics for that period of time.
A query like "the number of visitors and page views for each day in the 7 days before the 1st of February 2021"
falls into this category.
This is how to write this query:
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
// Build query
tsQuery := plausible.TimeseriesQuery{
Period: plausible.Last7Days().FromDate(plausible.Date{Day: 1, Month: 2, Year: 2021}),
Metrics: plausible.Metrics{
plausible.Visitors,
plausible.PageViews,
},
}
// Make query
queryResults, err := mysite.Timeseries(tsQuery)
if err != nil {
// handle error
}
// Iterate over the data points
for _, stat := range queryResults {
fmt.Printf("Date: %s | Visitors: %d | Pageviews: %d\n",
stat.Date, stat.Visitors, stat.Pageviews)
}
}
```
A breakdown query reports stats for the value of a given property over a period of time.
For instance, a query like "over the last 7 days what are the number of visitors and page views for each page of my
site" falls into this category.
Here's how to write such query:
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
// Build query
pageBreakdownQuery := plausible.BreakdownQuery{
Property: plausible.EventPage,
Period: plausible.Last7Days(),
Metrics: plausible.Metrics{
plausible.Visitors,
plausible.PageViews,
},
}
// Make query
pageBreakdown, err := mysite.Breakdown(pageBreakdownQuery)
if err != nil {
// handle error
}
// Iterate the results
for _, stat := range pageBreakdown {
fmt.Printf("Page: %s | Visitors: %d | Pageviews: %d \n",
stat.Page, stat.Visitors, stat.Pageviews)
}
}
```
This wrapper has support for the [site provisioning API](https://plausible.io/docs/sites-api).
However, note that this API is still private and requires a special token for the requests mentioned below to work. Make
sure you have a token with permissions for the site provisioning API before attempting to make these requests. You can
go here to know more about how to get a token for this API:
* [Plausible Docs: Site Provisioning API](https://plausible.io/docs/sites-api)
Gets a list of existing sites your Plausible account can access.
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
// Warning: This token must have permissions to the site provisioning API
client := plausible.NewClient("")
sites, err := client.ListSites()
if err != nil {
// handle error
}
fmt.Printf("Sites %s\n", sites.Sites)
}
```
If the response contains a lot of sites, it will be paginated. To access other pages, use the pagination options:
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
"github.com/andrerfcsantos/go-plausible/plausible/urlmaker/pagination"
)
func main() {
// Create a client with an API token
// Warning: This token must have permissions to the site provisioning API
client := plausible.NewClient("")
sites, err := client.ListSites(
pagination.After("awebsite"),
pagination.Before("otherwebsite"),
pagination.Limit(20),
)
if err != nil {
// handle error
}
fmt.Printf("Sites %s\n", sites.Sites)
}
```
Gets details of a site. Your Plausible account must have access to it.
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
// Warning: This token must have permissions to the site provisioning API
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
siteResult, err := mysite.Details()
if err != nil {
// handle error
}
fmt.Printf("Site %v\n", siteResult)
}
```
### Get or create Shared Links
Shared Links are URLs that you can generate to give others access to your dashboards.
You can use `SharedLink()` to get information for a link or create one with a given name. The call to get and create a
shared link it's the same - if a link with the given name already exists, it'll simply get the information for the
existent link. If the link does not exist, this call will create it and return the information of the newly created
link.
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
// Warning: This token must have permissions to the site provisioning API
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
sl := plausible.SharedLinkRequest{
Name: "Friends Link",
}
slResult, err := mysite.SharedLink(sl)
if err != nil {
// handle error
}
fmt.Printf("Name: %s | URL: %s\n", slResult.Name, slResult.URL)
}
```
It's also possible to create new sites using the site provisioning API. Attempting to create a site that already exists
will result in an error.
```go
package main
import (
"fmt"
"github.com/andrerfcsantos/go-plausible/plausible"
)
func main() {
// Create a client with an API token
// Warning: This token must have permissions to the site provisioning API
client := plausible.NewClient("")
newSiteRequest := plausible.CreateSiteRequest{
Domain: "mynewsite.com",
Timezone: "Europe/Lisbon",
}
// Note that we call CreateNewSite directly on the client,
// and not on a site like the majority of requests
siteResult, err := client.CreateNewSite(newSiteRequest)
if err != nil {
// handle error
}
fmt.Printf("Domain: %s | Timezone: %s\n", siteResult.Domain, siteResult.Timezone)
}
```
Push events with `site.PushEvent()`
```go
func main() {
// Create a client with an API token
client := plausible.NewClient("")
// Get an handler to perform queries for a given site
mysite := client.Site("example.com")
e := plausible.EventRequest {
EventData: EventData{
Domain: "example.org",
Name: "pageview",
URL: "https://example.com/awesome_page",
}
UserAgent: "user-agent"
}
_, err := client.PushEvent(e)
if err != nil {
// handle error
}
}
}
```
This project has tests in the form of Unit tests and Integration tests.
Unit tests are the easiest to run as they don't require any setup and do not attempt to make requests over the internet.
Unit tests start with `TestUnit`. This means that to run just the unit tests, you can do:
```bash
go test github.com/andrerfcsantos/go-plausible/plausible -run ^TestUnit
```
Integration tests attempt to make calls to the API. Because of this, they require configuration in the form of
environment variables. Set these environment variables before attempting to run the integration tests:
* `PLAUSIBLE_TOKEN` - API token to be used in the integration tests
* `PLAUSIBLE_DOMAINS` - A domain or a comma separated list of domains. The first domain on the list will be used to test
queries.
Integration tests start with the name `TestIntegration`. With these variable set, you can run only the integration tests
with:
```bash
go test github.com/andrerfcsantos/go-plausible/plausible -run ^TestIntegration
```
To run the unit tests, and the integration tests, just omit the `-run` flag:
```bash
go test github.com/andrerfcsantos/go-plausible/plausible
```
These integration tests do not include tests that require the site provisioning API. See below you to active tests for
the site provisioning API.
### Integration Tests with the provisioning API
Integration tests to the site provisioning API are disabled by default.
There are a couple of reasons for this:
* The provisioning API is still private and requires a token with special permissions. Most users will use a regular API
token, so these tests will not be relevant to them.
* The provisioning API allows the creation of sites and shared links, but the only way to reverse the actions of the API
is by manually deleting them via the dashboard. This also means that **the cleanup for these tests must be done
manually**.
With that said, if you really need to run these tests, set the following environment variable in addition to `PLAUSIBLE_TOKEN`
and `PLAUSIBLE_DOMAINS`:
* `PLAUSIBLE_PROVISIONING_TOKEN` - this must be set to an API token with permissions to the provisioning API.
With this variable set up, to run all tests (unit+integration tests) including the integration tests of the provisioning
API, add the flag `provisioning` to the `go test command`:
```bash
go test github.com/andrerfcsantos/go-plausible/plausible -flags=provisioning
```
If you encounter any bugs or have any comment or suggestion, please post them in
the [Issues section](https://github.com/andrerfcsantos/go-plausible/issues) of this repository.
All contributions are welcome!
Feel free to open PR's or post suggestions on
the [Issues section](https://github.com/andrerfcsantos/go-plausible/issues).
This project uses the [MIT License](https://github.com/andrerfcsantos/go-plausible/blob/main/LICENSE)