Go SDK

The official server-side Go SDK. The API mirrors the official Mixpanel Go SDK (mixpanel-go), so migrating is mostly a matter of swapping the import. Go 1.22+, zero dependencies, context-based.

Install

bash
go get github.com/cohorly-io/cohorly-go

Initialize

go
package main
import (
"context"
cohorly "github.com/cohorly-io/cohorly-go"
)
func main() {
client := cohorly.NewClient("YOUR_PROJECT_TOKEN",
cohorly.WithAPIHost("https://cohorly-service.velloalabs.com"))
ctx := context.Background()
err := client.Track(ctx, []*cohorly.Event{
client.NewEvent("signup", "user-1", map[string]any{
"plan": "premium",
}),
})
if err != nil {
// handle error
}
}

API

MemberNotes
NewClient(token, opts...)Options: WithAPIHost, WithHTTPClient.
client.NewEvent(name, distinctID, props)Stamps time (unix ms), $insert_id, $lib, $lib_version. AddTime / AddInsertID override for backfills.
Track(ctx, events)Chunks transparently at the server's 500-event batch cap. Batches are atomic server-side, safe to retry as-is.
PeopleSet / PeopleSetOnce / PeopleIncrement / PeopleUnset / PeopleDeleteProfile updates mapped to /engage ops.
Alias(ctx, alias, distinctID)POST /alias.
NewBufferedClient(client, opts...)Non-blocking Enqueue + background flush loop with the shared retry contract. Close(ctx) on shutdown.

Buffered mode

go
buffered := cohorly.NewBufferedClient(client,
cohorly.WithFlushInterval(10*time.Second),
cohorly.WithFlushBatchSize(50),
)
buffered.Enqueue(buffered.NewEvent("page_view", "user-1", nil))
// On shutdown: stop the loop and flush whatever is left.
if err := buffered.Close(ctx); err != nil {
// remaining events could not be delivered
}

The buffered client implements the shared Cohorly retry contract: exponential backoff on 429/5xx/network honoring Retry-After, batch halving on 413, permanent drop on 400, queue capped at 1000 (oldest dropped). It embeds *Client, so the synchronous methods stay available.

Error handling

go
err := client.Track(ctx, events)
if errors.Is(err, cohorly.ErrInvalidToken) {
// bad project token (HTTP 401)
}
var httpErr *cohorly.HTTPError
if errors.As(err, &httpErr) && httpErr.Status == 429 {
time.Sleep(httpErr.RetryAfter)
// safe to retry the same payload
}
PreviousPHP
NextIngestion