Web SDK
Add Flash Analytics to any browser app, SPA, or script-tag integration with one import.
The Web SDK handles page views, link clicks, data-attribute events, JavaScript errors, session access, A/B experiment assignments, and remote config — all from a single@flash-analytics/web import.
Installation
Install the package
npm install @flash-analytics/web@2.2.3pnpm add @flash-analytics/web@2.2.3Initialize once at app startup
Create a shared analytics.ts module and import it everywhere you track events.
import { FlashAnalytics } from '@flash-analytics/web';
export const analytics = new FlashAnalytics({
appId: process.env.FLASH_APP_ID!, // must be a UUID
capturePageViews: true,
captureExternalLinks: true,
captureDataAttributes: true,
captureErrors: true,
});appId must be a UUID
appId must be a valid UUID (e.g. 00000000-0000-4000-8000-000000000000). Placeholder strings will fail validation. Get your UUID from the Flash dashboard.Identify users after login
await analytics.identify({
profileId: 'user_123',
email: 'user@example.com',
properties: { plan: 'pro' },
});Track events
analytics.track('checkout_started', {
cartValue: 129.50,
currency: 'USD',
itemCount: 3,
});Auto-capture
Enable capture flags at init time — the SDK wires up the listeners automatically.
capturePageViewsFires on load and every history change
captureExternalLinksTracks outbound link clicks
captureDataAttributesClicks on fa-track annotated elements
captureErrorsGlobal errors and unhandled rejections
captureHashNavigationHash-only navigation changes
captureVariantsExperiment assignments on session start
Global properties
Call setGlobalProperties once and the SDK merges them into every subsequent event.
analytics.setGlobalProperties({
appVersion: '1.2.0',
plan: 'pro',
environment: 'production',
});Experiments
Enable captureVariants to automatically sync assignments on each new session and after identify().
// All cached assignments — no API call
const all = analytics.getAllExperiments();
// Single experiment — cache first, then API fallback
const assignment = await analytics.getExperimentById('checkout-cta');
console.log(assignment?.variantName); // 'variant_a' | 'control'
// Manual — always calls the API
const variant = await analytics.assignExperiment('checkout-cta');Remote config
const config = await analytics.fetchRemoteConfig({
country: 'US',
});
const enabled = config.getBoolean('new_checkout', false);
const title = config.getString('checkout_title', 'Checkout');
const maxItems = config.getNumber('max_cart_items', 50);Session access
Browser sessions are restored during SDK initialization when a valid cached session exists. Use getSession() for a synchronous read, and onSessionUpdated when another part of your app needs the session as soon as the SDK restores, creates, or refreshes it.
const analytics = new FlashAnalytics({
appId: 'YOUR_APP_ID',
onSessionUpdated(session) {
console.log(session.id);
console.log(session.estimatedExpiresAt); // epoch milliseconds
console.log(session.estimatedTtlMs); // number
},
});
const session = analytics.getSession();
console.log(session?.id);
console.log(session?.estimatedExpiresAt); // epoch milliseconds
console.log(session?.estimatedTtlMs); // numberThe callback can run during initialization if the Web SDK restores an unexpired session from sessionStorage or cookies. It also runs after a track(), identify(), or batch flush response returns session data.
localStorage. Session data uses sessionStorage and cookies so session restore works even if one storage mechanism is blocked.Script tag (no bundler)
<script>
window.fa = window.fa || function () {
var q = [];
return new Proxy(function () {
arguments.length && q.push([].slice.call(arguments));
}, {
get: function (_t, key) {
return key === 'q' ? q : function () {
q.push([key].concat([].slice.call(arguments)));
};
}
});
}();
window.fa('init', {
appId: 'YOUR_APP_ID',
capturePageViews: true,
captureErrors: true,
});
</script>
<script src="https://dashboard.flashanalytics.app/fa1.js" defer async></script>Batching
Enable batching for high-volume apps to reduce network calls. Queued events keep their original event timestamp, and session responses from batch flushes still update getSession() and onSessionUpdated.
const analytics = new FlashAnalytics({
appId: 'YOUR_APP_ID',
deliveryStrategy: {
strategy: 'batching',
config: {
size: 10, // flush when 10 events queued
timeout: 5000, // or every 5 seconds
fallbackToIndividual: true,
},
},
});
// Flush manually (e.g. before page unload)
await analytics.flushBatch();Web batching also flushes with keepalive on page hide and when the page becomes hidden, so queued events are released during normal browser lifecycle changes.