Server-side analytics SDK for Clamp Analytics in Go.
Send tracked events from any Go server to Clamp. Pure stdlib, no external dependencies. Module path: github.com/clamp-sh/analytics-go.
go get github.com/clamp-sh/analytics-goGo 1.21+ supported.
package main
import (
"context"
"log"
"os"
clamp "github.com/clamp-sh/analytics-go"
)
func main() {
clamp.Init("proj_xxx", os.Getenv("CLAMP_API_KEY"))
err := clamp.Track(context.Background(), "signup", clamp.Properties{
"plan": "pro",
"method": "email",
})
if err != nil {
log.Printf("clamp: %v", err)
}
}Get a server API key at https://clamp.sh/dashboard (Settings → API Keys, format sk_proj_...). Read it from the environment; never commit it.
Configures the SDK. Call once at process startup. Stores config in package-level state guarded by a mutex, so it's safe to use from concurrent goroutines.
Available options:
WithEndpoint(string): overrides the defaulthttps://api.clamp.sh.WithHTTPClient(*http.Client): supplies a custom HTTP client. Useful for setting timeouts, proxies, or a test transport.
Sends a server event. Returns nil on success.
ctx: standardcontext.Contextfor cancellation and timeouts.name: event name string.properties: optionalPropertiesmap. Values may bestring, integer types,float32/float64,bool, orMoney. Other types return a wrapped error.
Optional via TrackOption:
WithAnonymousID(string): links the event to a browser visitor.WithTimestamp(time.Time): overrides the event time. Times in non-UTC locations are normalized to UTC on the wire.
Returns:
ErrNotInitializedifInithas not been called.*HTTPErrorif the API responds with a non-2xx status.- A wrapped error for transport, marshaling, or context-cancellation failures.
type Money struct {
Amount float64
Currency string
}A typed monetary value. Use it for revenue, refunds, taxes; anywhere a currency-denominated amount belongs.
clamp.Track(ctx, "purchase", clamp.Properties{
"plan": "pro",
"total": clamp.Money{Amount: 29.00, Currency: "USD"},
"tax": clamp.Money{Amount: 4.35, Currency: "USD"},
})Amount is in major units (29.00, not 2900). Currency is an ISO 4217 code (uppercase, three letters).
Sends an error as a $error event. Convenience over Track that extracts the message and captures a stack trace via runtime.Stack at the call site. The server adds a stable fingerprint at ingest so the same bug groups across occurrences.
if err := processWebhook(ctx, payload); err != nil {
_ = clamp.CaptureError(ctx, err, clamp.WithErrorContext(clamp.Properties{
"webhook": "stripe",
}))
}Available options:
WithErrorContext(Properties): extra primitive properties; the reserved key"handled"is dropped.WithErrorAnonymousID(string): links the error to a browser visitor.WithErrorTimestamp(time.Time): overrides the event timestamp.
CaptureError(ctx, nil, ...) is a no-op. The error type is recorded as %T-formatted Go type name (e.g. *errors.errorString, *url.Error). Lengths are capped (error.message 1KB, error.type 64 chars, error.stack 16KB) to match server-side limits.
Per-framework integration patterns (net/http middleware, gin, echo, chi) are documented at https://clamp.sh/docs/sdk/go.
The SDK is synchronous and returns errors on failure. There are no automatic retries. If you want fire-and-forget behaviour, ignore the returned error or log it:
go func() {
if err := clamp.Track(ctx, "subscription_started", props); err != nil {
log.Printf("clamp: %v", err)
}
}()For high-throughput webhook handlers, defer the call to a worker pool or a queue (Redis, NATS, RabbitMQ).