Browse docs

Explore by section, then jump directly into a page.

Browser SDK

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

1

Install the package

Terminal
npm install @flash-analytics/web@2.2.4
Terminal
pnpm add @flash-analytics/web@2.2.4
2

Initialize once at app startup

Create a shared analytics.ts module and import it everywhere you track events.

analytics.tsTypeScript
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

The 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.
3

Identify users after login

TypeScript
await analytics.identify({
  profileId: 'user_123',
  email: 'user@example.com',
  properties: { plan: 'pro' },
});
4

Track events

TypeScript
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.

capturePageViews

Fires on load and every history change

captureExternalLinks

Tracks outbound link clicks

captureDataAttributes

Clicks on fa-track annotated elements

captureErrors

Global errors and unhandled rejections

captureHashNavigation

Hash-only navigation changes

captureVariants

Experiment assignments on session start

Global properties

Call setGlobalProperties once and the SDK merges them into every subsequent event.

TypeScript
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.

TypeScript
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.

Dashboard rule exampleTEXT
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 minutes

SDK-side allow and block rules

TypeScript
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().

TypeScript
// 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');
LifecycleProfileSessionEvent
New session from /trackfetchedfetchedfetched
identify()refreshedunchangedunchanged
Session expiryunchangedremovedunchanged

Remote config

TypeScript
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.

TypeScript
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);     // number

The 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.

Device ID is stored in cookies and localStorage. Session data uses sessionStorage and cookies so session restore works even if one storage mechanism is blocked.

Script tag (no bundler)

HTML
<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.

TypeScript
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.