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.4pnpm add @flash-analytics/web@2.2.4Initialize 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',
});Dashboard collection controls and session timeout
The Web SDK automatically receives dashboard-managed collection settings and applies them in the browser before events are sent. It can drop blocked events, remove blocked properties, use dashboard batching defaults, and cache the current session timeout locally.
const analytics = new FlashAnalytics({
appId: 'YOUR_APP_ID',
collectionConfig: true,
maxSessionTimeoutInMin: 15,
});maxSessionTimeoutInMin controls local session expiry and heartbeat timing, is sent to the backend, and is cached per client. System events sdk_initialized and sdk_heartbeat are always allowed.
Allow events:
page_view
signup_clicked
checkout.*
Block events:
debug.*
ad_test_noise
For checkout.completed, allow only:
orderId
amount
currency
couponCode
Block these properties everywhere:
password
authToken
emailRaw
Client-level override for website-prod:
block property internalCampaignId
batching: 10 events or 5 seconds
session timeout: 30 minutesSDK-side allow and block rules
const analytics = new FlashAnalytics({
appId: 'YOUR_APP_ID',
allowEvents: [
{
name: 'checkout.completed',
allowProperties: ['orderId', 'amount', 'currency'],
blockProperties: ['debugPayload'],
},
{ name: 'page_view' },
],
blockEvents: ['debug.*', 'internal_test'],
blockProperties: ['password', 'authToken', 'emailRaw'],
shouldTrack(payload) {
return !(payload.type === 'track' && payload.payload.name.startsWith('dev.'));
},
});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');| Lifecycle | Profile | Session | Event |
|---|---|---|---|
| New session from /track | fetched | fetched | fetched |
| identify() | refreshed | unchanged | unchanged |
| Session expiry | unchanged | removed | unchanged |
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.