Browse docs

Explore by section, then jump directly into a page.

Node.js / Backend

Core / Node.js SDK

The base SDK for Node.js services, backend workers, CLIs, and any custom JavaScript integration.

@flash-analytics/sdk is the shared core used by all browser wrappers. Use it directly when you need server-side tracking — background jobs, payment webhooks, admin scripts, or any non-browser runtime.

Installation

1

Install the package

Terminal
npm install @flash-analytics/sdk@2.2.3
Terminal
pnpm add @flash-analytics/sdk@2.2.3
2

Set environment variables

.envTerminal
FLASH_ANALYTICS_CLIENT_ID=00000000-0000-4000-8000-000000000000
FLASH_ANALYTICS_SECRET_KEY=your-secret-key
The secret key is safe to use server-side. Never expose it in browser bundles or public environment variables.
3

Create the SDK instance

lib/analytics.tsTypeScript
import { FlashAnalytics } from '@flash-analytics/sdk';

export const analytics = new FlashAnalytics({
  appId: process.env.FLASH_ANALYTICS_CLIENT_ID!,
  secretKey: process.env.FLASH_ANALYTICS_SECRET_KEY,
  platform: 'node',
  appVersion: process.env.npm_package_version,
  deliveryStrategy: {
    strategy: 'batching',
    config: {
      size: 25,
      timeout: 5000,
      fallbackToIndividual: true,
    },
  },
});
4

Track events

TypeScript
import { analytics } from './lib/analytics';

// Identify a user (attach a profileId to future events)
await analytics.identify({ profileId: 'user_123', email: 'user@example.com' });

// Track a named event with properties
await analytics.track('invoice_paid', {
  profileId: 'user_123',
  invoiceId: 'inv_456',
  amount: 99.00,
  currency: 'USD',
});

// Flush the batch before the process exits
await analytics.flushBatch();

Core APIs

track(name, props?)

Send a named event

identify(payload)

Set profileId and user properties

setGlobalProperties(props)

Merge into every subsequent event

revenue(amount, props?)

Record a charge or purchase

increment(payload)

Add to a numeric user property

decrement(payload)

Subtract from a numeric user property

getSession()

Read session ID and expiry

fetchRemoteConfig(opts)

Pull feature flag values

assignExperiment(id)

Get an A/B assignment

flushBatch()

Force-send queued events

Global properties

Call setGlobalProperties once at startup to tag every event with context.

TypeScript
analytics.setGlobalProperties({
  service: 'billing-worker',
  environment: process.env.NODE_ENV,
  version: process.env.npm_package_version,
});

Session updates

Use getSession() when you need to read the latest session synchronously. Use onSessionUpdated when another layer needs the session as soon as the SDK receives, restores, or refreshes it.

TypeScript
const analytics = new FlashAnalytics({
  appId: process.env.FLASH_ANALYTICS_CLIENT_ID!,
  secretKey: process.env.FLASH_ANALYTICS_SECRET_KEY,
  onSessionUpdated(session) {
    console.log(session.id);
    console.log(session.estimatedExpiresAt);
    console.log(session.estimatedTtlMs);
  },
});

const session = analytics.getSession();
console.log(session?.id);

The callback runs after successful tracking responses return session data. In browser wrappers it can also run during initialization when a valid cached session is restored.

Batching

Enable batching for high-throughput workers. Events are timestamped when they enter the queue, not when the batch is flushed, so ordering reflects real activity time. Batch responses update the same session cache used by getSession() and onSessionUpdated.

TypeScript
const analytics = new FlashAnalytics({
  appId: process.env.FLASH_ANALYTICS_CLIENT_ID!,
  deliveryStrategy: {
    strategy: 'batching',
    config: {
      size: 25,                     // flush after 25 events
      timeout: 5000,                // or every 5 seconds
      fallbackToIndividual: true,   // retry individually if batch fails
    },
  },
});

// Always flush at process exit
process.on('beforeExit', async () => {
  await analytics.flushBatch();
});

Remote config

TypeScript
const config = await analytics.fetchRemoteConfig({
  profileId: 'user_123',
  userProperties: { plan: 'pro' },
  country: 'US',
});

const enabled  = config.getBoolean('new_checkout', false);
const title    = config.getString('checkout_title', 'Checkout');
const maxItems = config.getNumber('max_cart_items', 50);
const theme    = config.getJson('theme_config', {});

Experiments

TypeScript
// Enable auto-assignment at init
const analytics = new FlashAnalytics({
  appId: process.env.FLASH_ANALYTICS_CLIENT_ID!,
  captureVariants: true,
});

// Cache first, API fallback
const assignment = await analytics.getExperimentById('checkout-cta');
console.log(assignment?.variantName);

// Manual assignment (always calls the API)
const variant = await analytics.assignExperiment('checkout-cta', {
  profileId: 'user_123',
});

Server-side tracking tip

Always pass profileId in your track calls when you know the user. Server-side events without a profileId are linked by session only, which may result in fragmented user journeys in the dashboard.