staqlydocs

Analytics

Optional product analytics and error reports to your own PostHog project. Off unless you set POSTHOG_KEY.

Edit on GitHub

staqly can send a small, fixed set of product events and its error reports to a PostHog project of yours. It is off by default: an install without POSTHOG_KEY sends nothing anywhere and the dashboard never loads the PostHog script. staqly cloud (app.staqly.ai) turns it on for its own project.

POSTHOG_KEY=phc_yourProjectToken          # Project settings › Project token (public: it can only send events)
POSTHOG_HOST=https://eu.i.posthog.com     # default; https://us.i.posthog.com, self-hosted PostHog or a reverse proxy
POSTHOG_ENVIRONMENT=production            # default; use development or test on other servers

Pass them like any other setting.

What is sent

SourceWhatHow
Server (app=api)The product events below, after the change they describe is savedposthog-go, batched in memory, sent in the background; at most 5 s to send what is left at shutdown
Server (app=api)Error reports: every ERROR log line (5xx, panics, failing workers) as an exceptionSame client; see Logs & tracing
Dashboard (app=dashboard)Page views, Core Web Vitals and unhandled errors (including errors the pages' error boundaries catch)posthog-js, loaded after the page only when the server has POSTHOG_KEY, from your own server (no third-party scripts)

Every event carries environment, release (the server's version) and app. PostHog being slow or down never slows a request: events wait in memory and are dropped if it stays unreachable.

Identification

  • A person is their user id (usr_...), never an email address or a name, and only on server events. Events a person causes through an API key are theirs too (actor=api_key).
  • Work staqly does for a workspace (publishing, Stripe webhooks) and every event of a local install has no person: it is the workspace's (workspace:<id>, PostHog's personless events).
  • Every server event has workspace_id; activation and publishing are counted per workspace.
  • The dashboard is cookieless: nothing is stored in the browser, there is no person and no link to the server's events. A visitor is a hash of the day, address and browser that PostHog computes and forgets the next day.

Never sent

Post text, comments, media, file names, channel names and handles, collection names, email addresses, names, URLs of published posts, access tokens, API keys, cookies, passwords, OAuth codes and Stripe card details. Dashboard URLs are sent without their query string and fragment (sign-in, invitation and preview links carry tokens there). No clicks or text are captured (autocapture is off) and sessions are never recorded.

Event catalog

Names are snake_case, past tense, object_action. Properties appear on the event they are listed with; workspace_id, actor (session, api_key, local, system) and, when an agent acted, agent (the MCP or REST client's name, e.g. Claude Code) are on every server event.

EventWhenProperties
user_signed_upA new account (cloud)method (google, email)
user_signed_inA sign-inmethod (google, email, passkey, access_token, api_key)
sign_in_failedA sign-in that did not go through (personless)method, code (e.g. invalid_code, login_expired)
user_activeFirst authenticated request of a person in a workspace each day—
workspace_createdA new workspace—
member_invited, member_joinedInvitationsrole
channel_connectedA channel connected or reconnectedplatform, reconnected
channel_disconnected, channel_needs_reconnectA channel removed / its sign-in stopped workingplatform
post_created, post_scheduledA post created / scheduledstatus, channel_count, platforms, media_count, thread_parts, repeats
post_updatedA post saved—
post_publishedOne channel of a post went outplatform, attempts, delay_seconds (how late after the due time)
post_publish_failedOne channel of a post failed for goodplatform, attempts, error_class (reauth, rejected, timeout, start_failed, credentials, limit, validation, platform_error), error (the platform's message, at most 200 characters)
schedule_created, schedule_failedSchedules—
media_uploadedA file uploadedtype (image, video...), size_bytes
media_editedThe media editor saved a file or a projectkind (file, project)
ai_image_requestedAn AI picture (media editor)op, model, duration_ms, ok
api_key_created, webhook_created, alert_createdIntegrations—
checkout_startedA Stripe checkout was opened (cloud)plan, interval, trial
plan_changedA workspace's plan changed (Stripe webhooks, the operator CLI, trials)from, to, reason (e.g. stripe:active, stripe:canceled)
subscription_payment_failedStripe says a renewal did not go through (past_due, incomplete)status, plan
credits_purchasedA bundle of extra posts paidposts
$exceptionAn error report (server or dashboard)PostHog's exception properties; server: request_id, trace_id, route, workspace_id, worker and the log line's fields
$pageview, $web_vitalsDashboard pagesPostHog's, URL without query and fragment

Billing numbers in PostHog are counts of what the server confirmed from Stripe webhooks, not revenue: MRR, ARR and churn come from Stripe.

Adding an event

  1. Prefer a domain event that already exists: map it in analyticsEvents in apps/api/internal/app/analytics.go and pick its properties in trackEvent. It is sent only after its transaction commits, once.
  2. For something with no domain event, call s.trackAs(q, p, "noun_verbed", "key", value) (pass the transaction's q inside s.tx, nil outside one).
  3. Properties are enums, counts and ids. Never text people wrote, names, addresses or URLs.
  4. Add it to the table above and a case to analytics_internal_test.go.

Cost

PostHog's free tier (checked October 2026) covers 1 million events, 100,000 exceptions and 5 insight alerts a month. staqly sends one event per action above, at most one user_active per person, workspace and day, and in the dashboard one page view per navigation plus web vitals; no autocapture, page leave, heatmap or recording events. Set a billing limit in PostHog to be sure. Group analytics is a paid PostHog add-on, so workspaces are a property (workspace_id), not a group.

Privacy

If you turn this on for people other than yourself, you are the controller of that data: say so in your privacy policy. The dashboard sets no cookies for analytics. PostHog derives an approximate location from the IP address of each request; turn on Discard client IP data in the PostHog project if you don't want it. Event retention follows your PostHog plan.

On this page