Skip to main content

Frontend telemetry

Toggly client SDKs can send compact, aggregated feature-evaluation and application-metric telemetry from browser, mobile, desktop, and WebAssembly clients. Each SDK page shows the exact configuration and API names for that platform.

Frontend telemetry is enabled by default when a public application key is configured. Set enableTelemetry to false to opt out. A missing application key also disables the reporter completely: it buffers no telemetry and starts no telemetry timer, lifecycle listener, or request. Server-side rendering, builds, and trusted server or edge clients do not create a frontend reporter.

Use the package versions below or newer compatible releases. They cover the compact reporter and the session APIs described here.

SDK quick reference​

The following versions support the documented compact frontend reporter and session APIs. The examples on each SDK page show where configuration belongs and which object owns cleanup.

SDKVersion to useConfigurationExplicit API and owner
JavaScript@ops-ai/feature-flags-toggly 1.9.0Toggly.init(...)Static Toggly.recordUsage, recordView, incrementCounter, setGauge, and flushTelemetry; Toggly.init replaces the single browser owner
Angular@ops-ai/ngx-feature-flags-toggly 2.9.0provideToggly(...) or NgxFeatureFlagsTogglyModule.forRoot(...)Injected TogglyService; Angular destroys the service owner with its injector
React@ops-ai/react-feature-flags-toggly 1.12.0new Toggly(...) or createTogglyProvider(...)Service methods; a provider factory retains one owner until its final unmount, while directly owned services require dispose()
Vue@ops-ai/vue-feature-flags-toggly 1.10.0app.use(toggly, options)The app-injected service; app.unmount() releases the app owner, and standalone services require dispose()
Svelte@ops-ai/svelte-feature-flags-toggly 1.11.0createToggly(...)Package functions or store methods; replacing or disposing the store releases its reporter
SvelteKit@ops-ai/toggly-sveltekit 0.2.0Browser createToggly(snapshot, options)Store methods; keep one store across route refreshes and call dispose() when the owning layout ends
Solid@ops-ai/solid-feature-flags-toggly 0.3.0createToggly(...) or createClient(...)Owner methods; Solid cleanup handles reactive owners, while a lower-level client requires dispose()
Next.js@ops-ai/nextjs-toggly-client 1.5.0TogglyProvider browser configuseToggly().telemetry; provider unmount releases the browser owner
Nuxt@ops-ai/nuxt-toggly-client 1.3.0 / Core 1.13.0Client createToggly(...) or Nuxt module browser configclient.telemetry; replacing the browser client releases the old owner
React Router@ops-ai/react-router-toggly 1.1.0TogglyProvider or RouterTogglyProvider configMethods returned by useToggly(); provider unmount releases its reporter
Astro@ops-ai/astro-feature-flags-toggly 1.16.0Integration options or initTogglyClient(...)Client-store functions; destroyTogglyClient() releases the shared browser owner
Gatsby@ops-ai/gatsby-feature-flags-toggly 1.10.0Gatsby plugin browser optionsPackage functions or useToggly().telemetry; provider replacement or unmount releases the owner
Docusaurus@ops-ai/toggly-docusaurus-plugin 0.10.0Plugin/provider optionsuseToggly() methods; final provider unmount releases the browser owner
Generic client core@ops-ai/toggly-client-core 0.5.1createTogglyClient(...)Client methods; call dispose() when the browser owner ends
Flutterfeature_flags_toggly 1.12.0TogglyConfigStatic Toggly methods; Flutter lifecycle backgrounding flushes and Toggly.dispose() releases the owner
iOSios-sdk-v1.5.2TogglyConfigAsync TogglyService or Toggly.shared methods; forward .background and dispose owned services
AndroidAndroid SDK 1.8.0TogglyConfigTogglyService, Toggly, Compose, and Views facades; forward AppStateType.BACKGROUND and dispose owned services
.NET clientToggly.FeatureManagement.Client 3.10.0TogglyClientOptionsTogglyClient implements IFrontendTelemetry; DisposeAsync() releases the owner
Blazor WebAssemblyToggly.FeatureManagement.Blazor 3.10.0TogglyClientOptionsBrowser session implements IFrontendTelemetry; its DI scope owns cleanup
Electron@ops-ai/electron-feature-flags-toggly 1.1.0Main-process initToggly(...)Main client owns one reporter shared over authorized IPC; attachTogglyLifecycle(...) handles suspend and bounded quit cleanup
React Native@ops-ai/react-native-toggly 1.4.0 with Core 1.8.0TogglyProvider props or Core TogglyConfiguseToggly() or Core service methods; provider AppState/background and final unmount use the same Core owner

The Next.js and Nuxt trusted server and edge reporters retain their existing telemetry gateways and APIs. The rows above describe their browser companions. Solid/SolidStart requires 0.3.0 or a newer compatible release for these APIs.

The deprecated Remix packages do not gain a separate reporter; migrate to the React Router SDK. The generated CSS/HTML SDK has no JavaScript runtime in which to report frontend telemetry. The maintained WordPress PHP integration remains a server integration and does not add this browser reporter. To measure browser interactions on CSS/HTML or WordPress pages, initialize the JavaScript SDK with a public Front-end App Key and record usage/views from page interactions. Keep the maintained PHP and Blazor Server integrations for their server work.

Configuration​

Names follow each platform's conventions, but the values are consistent:

SettingDefaultBehavior
enableTelemetrytrue with an app keyMaster switch for frontend telemetry
enableUsageTrackingtrue where exposedAutomatic checks and explicit usage/view events
enableMetricstrue where exposedApplication counters and gauges
metricsBaseUrlhttps://metrics.toggly.ioIndependent telemetry base URL
telemetryFlushIntervalMs45000Base flush interval; valid values are 30,000–60,000 ms

Each interval is jittered by ±20% so clients do not flush at the same instant. An invalid interval falls back to 45 seconds. An invalid telemetry endpoint disables that reporter and emits a bounded diagnostic; neither condition stops feature initialization or evaluation. Custom endpoints must be absolute HTTP or HTTPS URLs without credentials, query strings, or fragments.

The telemetry endpoint is independent of the definitions endpoint. Definition query parameters, authorization headers, groups, claims, and entity attributes are never copied onto the metrics URL. Optional compact body fields i and u are the only identity sent with a telemetry batch; see Identity.

What is recorded​

An automatic check is recorded once for each feature that an application actually evaluates. Local and entity gates resolve first; aggregate negation is applied afterward. all and any gates keep their normal short-circuit behavior, so skipped keys are not counted. A later real UI recomputation counts again, while cache hydration, refresh projection, and framework snapshot reads do not.

Where an SDK already returns an assigned variant, the check uses that variant. Boolean-only SDKs use enabled or disabled. Variant names contain 1–64 ASCII letters, digits, underscores, or hyphens.

Usage and view events are always explicit. Rendering a component or returning an enabled flag does not automatically mark the feature as used or viewed.

recordUsage(featureKey, variant = "enabled")
recordView(featureKey, variant = "enabled")
incrementCounter(metricKey, value = 1)
setGauge(metricKey, value)
flushTelemetry()

Counters accept nonnegative integer increments up to 1,000,000 per call and sum within a buffered window. Gauges accept finite nonnegative values up to 1,000,000 and keep the latest value. Define and allowlist feature and business metric names in Toggly before reporting them. Metric names are application-level names; they are not attached to a feature, identity, or label set. The server's metric definition decides whether a configured metric is a counter or gauge.

Privacy and resource limits​

The compact request contains only:

  • the application key and environment;
  • feature → variant aggregate counts for checked, used, and viewed events;
  • application-level metric values; and
  • optional minted instance id i, or client-asserted identity u when i is absent.

It contains no groups, claims, entity data, timestamps, or metric kind. Data stays in memory and is not persisted by storage companions. HTTP 202 acknowledges transport; it does not prove that a client-generated u was attributed. The application toggle Accept client-generated identities for metrics defaults off. Wire formats, key types, and mint curl live in the Metrics API Reference and Metrics authentication.

Each request is limited to 48 KiB of uncompressed UTF-8 JSON. A reporter keeps at most 2,000 admitted entries and 256 KiB across queued and in-flight work, with at most 16 variants per feature. Oversized or invalid new events are rejected without evicting already accepted events.

Delivery and lifecycle​

Clients send POST {metricsBaseUrl}/api/frontend/telemetry. Each request attempt has a five-second timeout.

Ordinary flushes prefer gzip and fall back to JSON if compression fails before sending. Browser hidden and page-exit flushes use uncompressed fetch with keepalive; native SDKs forward their platform background event. Requests omit credentials.

Only HTTP 202 acknowledges a batch. The reporter retries only explicit HTTP 429 and 503 responses, at most twice, after 30 and 60 seconds while honoring a longer readable Retry-After. Batches expire after five minutes. Network, timeout, abort, and other ambiguous failures are contained and are not replayed, because the server may already have accepted that batch. A 202 response acknowledges transport acceptance; it does not prove that an undefined or wrongly typed metric was retained.

Each client owner has one reporter. Replacing or disposing the client releases its timers, listeners, requests, and reconnect work without relabeling queued events for a new application or environment. Synchronous disposal starts at most one bounded best-effort final envelope. If you need to drain work before teardown, await the SDK's explicit flush method first; this is still best-effort and does not guarantee server acknowledgement.

Identity​

Mint only from a trusted backend that holds a Backend application key:

POST https://metrics.toggly.io/api/frontend/identities

There is no CORS on mint. Pass the returned opaque instanceId into the client SDK (not the Backend key). Definitions then use ?i=<instanceId> and omit u / g / claim.* on that request. Telemetry sends the same token as body field i.

When you do not mint, definitions keep ?u= / ?g= / claim.*. Telemetry may include body u from the client's current identity; ingest attributes that value only if the application toggle is on.

Unknown or expired i is stripped. The packet still returns 202, and definitions with unresolved i evaluate without extra client u/g/claims on the same request.

Switching sessions​

Pass only the minted token, never the Backend key, to a client's instanceId option (InstanceId on .NET). Mint a replacement when your application changes the trusted session, then apply it through the SDK's context API. Clear the old token explicitly on logout and clear old groups/claims where those are mutable. Blank tokens return to client-asserted u attribution; some native SDKs return to a device identity rather than removing identity entirely.

Already admitted events retain their original i or u; rotating context never relabels an old batch. Async evaluations capture the context they began with, and stale results must not become a new user's feature snapshot. Await context transitions before starting new-user interactions. The context API owns the session boundary. A flush only attempts delivery of admitted events with their original attribution.

The SDK guides' Session identity sections show the owning API and clearing rules. These differ: for example generic client-core, Astro, and Gatsby retain a token when only identity changes, whereas Next.js and Nuxt clear an omitted token on identity changes. Docusaurus uses provider config and SvelteKit uses new server snapshots. Do not substitute one SDK's reset method for another's.

Analytics hooks may send separate provider events; they do not create another compact reporter. Storage adapters persist feature data only, not telemetry.