Events & buffering
Every user action becomes an event. The SDK queues events in a buffer, batches them, and ships each batch to the API. This page explains the shape, timing, and knobs.
Event types
| Type | When it fires | Payload |
|---|---|---|
full_snapshot | On init, and every 30s during active session | Full DOM tree |
incremental_snapshot | On any DOM change | The diff |
mousemove | ~20Hz, throttled | [x, y] stream |
scroll | ~7Hz, throttled | Scroll offsets |
mouse_click | On click | Target element path + position |
input | On input change | Value (masked by default) |
navigation | On pushState / popstate | New URL |
network_request | On fetch/XHR complete | URL, method, status, timing |
console_log | On console.log/warn/error | Level + message |
js_error | On unhandled error | Stack trace |
identify | On identify() call | User ID + traits |
session_meta | On session start | Viewport, user agent, referrer |
page_view | On route change | URL + title |
rage_click | On 3+ clicks in same spot within 1s | Position + count |
Buffering
Events don't ship one-at-a-time. They accumulate in an in-memory buffer. The buffer flushes when either trigger fires first:
| Trigger | Default | Option |
|---|---|---|
| Time since last flush | 5000 ms | flushIntervalMs |
| Event count | 50 events | flushMaxEvents |
<GalachaProvider
projectKey="..."
flushIntervalMs={3000}
flushMaxEvents={100}
/>Lowering flushIntervalMs means faster replay-to-dashboard latency at the cost of more HTTP requests. Raising it batches more aggressively.
Flushing on page unload
The SDK hooks visibilitychange and pagehide. When the tab hides or closes, it flushes synchronously via navigator.sendBeacon so the last events don't get lost.
Ordering guarantees
- Events within a single batch are ordered by timestamp.
- Events across batches can arrive out of order if the network is flaky. The dashboard reorders by timestamp on read.
- The
full_snapshotis always the first event of a session. If that batch fails, subsequent incremental events are useless — the dashboard drops them (shows as "zombie session").
Payload size
- Each batch is gzipped before POST.
- Average batch: 2–8 KB compressed.
- A 3-minute active session ships ~80 KB total.
- Upload happens over HTTPS to
api.galacha.me/api/v1/events.
Manual flush
Not available on web. Available on React Native only:
Galacha.flush();Use cases: right before a crash handler, right before submitting a form you know is risky.
Custom events (React Native only)
Galacha.track("checkout_completed", {
amount: 49_990,
currency: "TZS",
});Custom events land in the session timeline alongside automatic events. See Custom events (RN).
On web, there is no Galacha.track() — the auto-capture catches everything unhandled, so it's rarely needed. If you want to annotate a specific moment, use a console.log (captured by captureConsole).
Dropping events
The SDK drops events silently when:
- The buffer overflows (> 10,000 events queued without successful flush)
- The API returns 429 (rate limit) — the current batch is dropped, flush resumes after a backoff
- The API returns 4xx (auth error) — all buffered events for that session are dropped