Analytics
@grounded/analytics is the browser product-analytics half of Grounded instrumentation.
Use it when you want Grounded to understand what the user did in the product, not just what the llm did on the server.
What It Covers
- browser-side
identify,page, andtrack - stable
sessionIdandanonymousId getContext()for forwarding browser identity into backend traces- batched delivery to
/api/telemetry/batch - optional FullStory mirror mode
Basic Usage
import { init } from '@grounded/analytics';
const analytics = init({
apiKey: process.env.NEXT_PUBLIC_GROUNDED_PUBLISHABLE_KEY!,
agentId: 'agt_support',
baseUrl: process.env.NEXT_PUBLIC_GROUNDED_BASE_URL ?? 'http://localhost:3001',
mirror: { fullstory: window.FS },
});
analytics.identify('user_123', { plan: 'pro' });
analytics.page();
analytics.track('checkout_started', { sku: 'pro-monthly' });
await analytics.flush();Browser-To-Server Handoff
This is the main correlation contract:
const context = analytics.getContext();
await fetch('/api/support/reply', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
message,
grounded: context,
}),
});Then on the server:
const trace = tracing.startTrace({
sessionId: req.body.grounded.sessionId,
anonymousId: req.body.grounded.anonymousId,
userId: req.body.grounded.userId,
name: 'support.reply',
resource: {
agentId: 'agt_support',
snapshotId: 'snap_live',
},
});That handoff is what lets Grounded merge browser telemetry and backend llm traces into one session timeline.
Event Types
identify(userId, traits?)
- stores the current
userId - sends an
identifyevent - mirrors to FullStory if configured
page(input?)
- sends a page-view style event
- captures
urlandtitle - merges in
referrerwhen available
track(name, properties?)
- sends a product event
- keeps the API provider-agnostic
- mirrors to FullStory if configured
getContext()
getContext() returns:
type AnalyticsContext = {
sessionId: string;
anonymousId: string;
userId?: string;
}Forward it to your backend on any request where you also emit @grounded/tracing spans.
FullStory Mirror Mode
If you already use FullStory, pass mirror.fullstory.
Grounded still sends its own normalized telemetry batch, but it also forwards:
identifytrack
to FullStory so you do not have to choose one or the other.
Delivery Model
@grounded/analytics:
- keeps events in memory until flush
- retries
429and5xx - restores the batch to the local queue on failure
- persists the stable identifiers through browser storage
If you need a hard flush before navigation or teardown, call:
await analytics.flush();Notes
- this package is browser-focused
- it does not create sessions directly
- it writes telemetry; Grounded derives sessions later
- publishable keys for analytics still use the
traces:writescope today