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
Install the package
npm install @flash-analytics/sdk@2.2.4pnpm add @flash-analytics/sdk@2.2.4Set environment variables
FLASH_ANALYTICS_CLIENT_ID=00000000-0000-4000-8000-000000000000
FLASH_ANALYTICS_SECRET_KEY=your-secret-keyCreate the SDK instance
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,
},
},
});Track events
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.
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.
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.
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();
});Dashboard collection controls
Supported SDKs automatically sync collection settings from the Flash dashboard. You can allow or block event names, allow or block event properties, set project-wide blocked properties, and define client-level overrides for specific apps or environments. Rules are applied before network delivery, so blocked events are dropped locally and blocked properties are removed before payloads leave your process.
const analytics = new FlashAnalytics({
appId: process.env.FLASH_ANALYTICS_CLIENT_ID!,
secretKey: process.env.FLASH_ANALYTICS_SECRET_KEY,
// Defaults to true. Leave enabled to use dashboard-managed rules.
collectionConfig: true,
// Optional local override. Also sent to the backend and cached per client.
maxSessionTimeoutInMin: 15,
});sdk_initialized and sdk_heartbeat bypass user collection filters so session maintenance continues even when normal product events are restricted.
Allow events:
checkout.started
checkout.completed
account.*
Block events:
debug.*
internal_test
For checkout.completed, allow only:
orderId
amount
currency
plan
Block these properties everywhere:
password
token
ssn
rawCardNumber
Client-level override for backend-prod:
block property internalTraceId
max session timeout: 15 minutes
batching: 25 events or 5 secondsThe same dashboard area can manage SDK defaults such as batching size, flush interval, session timeout, remote config values, and experiment assignment behavior. Code-level options are still available when you need an explicit environment override.
SDK-side allow and block rules
Add local rules when filtering must live in code. These rules are useful for dev builds, one-off clients, or guardrails that should run before the request is sent.
const analytics = new FlashAnalytics({
appId: process.env.FLASH_ANALYTICS_CLIENT_ID!,
secretKey: process.env.FLASH_ANALYTICS_SECRET_KEY,
allowEvents: [
{
name: 'invoice.paid',
allowProperties: ['invoiceId', 'amount', 'currency'],
blockProperties: ['internalLedgerId'],
},
{ name: 'account.*' },
],
blockEvents: ['debug.*', 'internal_test'],
blockProperties: ['password', 'authToken', 'ssn'],
shouldTrack(payload) {
if (payload.type === 'track' && payload.payload.name === 'health_check') {
return false;
}
return true;
},
shouldCaptureRequest(url, payload) {
return !url.includes('/track') || payload.type !== 'track' || process.env.NODE_ENV === 'production';
},
});Remote config
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
// 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
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.