Go SDK Pro
Send events from any Go server using a project API key. Pure stdlib, no external dependencies. Works with net/http, gin, echo, chi, and any other Go service.
Paste to your agent
Install
go get github.com/clamp-sh/analytics-goGo 1.21+ supported. The package depends only on the standard library.
Use an API key that starts with sk_proj_ from Settings → API Keys. Keys are scoped to one project. Read it from the environment; never commit it.
Quick start
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)
}
}API
Init(projectID, apiKey string, opts ...InitOption)
Configures the SDK. Call once at process startup. State is held at the package level behind 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 (for timeouts, proxies, or test transports).
Track(ctx, name, properties, opts...) error
Sends a server event. Returns nil on success.
ctx:context.Contextfor cancellation and timeouts.name: event name string.properties: optionalPropertiesmap. Values may bestring, integer types,float32/float64,bool, orMoney.
Optional via TrackOption:
WithAnonymousID(string): links the event to a browser visitor.WithTimestamp(time.Time): overrides the event time. Non-UTC times 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-cancel.
Money
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. Currency is an ISO 4217 code (uppercase, three letters).
Framework integrations
net/http
func signupHandler(w http.ResponseWriter, r *http.Request) {
user, err := createUser(r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
anonID, _ := r.Cookie("clamp_aid")
_ = clamp.Track(r.Context(), "signup", clamp.Properties{
"plan": user.Plan,
"method": "email",
}, clamp.WithAnonymousID(anonID.Value))
http.Redirect(w, r, "/welcome", http.StatusSeeOther)
}gin
func checkoutHandler(c *gin.Context) {
var payload CheckoutPayload
if err := c.BindJSON(&payload); err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
session := createStripeSession(payload)
_ = clamp.Track(c.Request.Context(), "checkout_started", clamp.Properties{
"plan": payload.Plan,
}, clamp.WithAnonymousID(payload.AnonID))
c.JSON(http.StatusOK, gin.H{"url": session.URL})
}echo
func featureUsed(c echo.Context) error {
user := c.Get("user").(*User)
_ = clamp.Track(c.Request().Context(), "feature_used", clamp.Properties{
"feature": c.Param("feature"),
"plan": user.Plan,
})
return c.NoContent(http.StatusNoContent)
}Errors and retries
The SDK is synchronous and returns errors on failure. There are no automatic retries. Either ignore the error (fire-and-forget), log it, or hand off to a queue:
go func() {
if err := clamp.Track(ctx, "subscription_started", props); err != nil {
log.Printf("clamp: %v", err)
}
}()Linking browser and server events
Pass the anonymous ID from the browser to your API, then use clamp.WithAnonymousID() on server-side calls. See the linking pattern on the server-side docs page; the same pattern applies in Go.
Links
- pkg.go.dev: github.com/clamp-sh/analytics-go
- Source: github.com/clamp-sh/analytics-go