@signal-js/node
v1.0.6
Published
Signal SDK for Node.js - Server-side event capture and analytics
Maintainers
Readme
@signal-js/node
Signal SDK for Node.js - Server-side event capture and analytics. Uses @signal-js/core and @signal-js/browser (for HttpEventSink); both are included as dependencies.
Installation
npm install @signal-js/node
# or
pnpm add @signal-js/node
# or
yarn add @signal-js/nodeQuick Start
import { createSignalNode } from '@signal-js/node';
const signal = createSignalNode({
endpoint: 'https://your-api.com',
apiKey: 'your-api-key',
});
// Capture an event
signal.capture({
distinctId: 'user-123',
event: 'purchase_completed',
properties: {
amount: 99.99,
currency: 'USD',
},
});
// Identify a user
signal.identify({
distinctId: 'user-123',
properties: {
email: '[email protected]',
name: 'John Doe',
plan: 'premium',
},
});
// Associate with a group
signal.group('user-123', 'company', 'acme-corp', {
name: 'Acme Corp',
plan: 'enterprise',
});
// Graceful shutdown
await signal.shutdown();Configuration
const signal = createSignalNode({
// Required
endpoint: 'https://your-api.com',
apiKey: 'your-api-key',
// Optional
projectId: 'my-project', // Default: 'default'
debug: false, // Enable debug logging
flushBatchSize: 20, // Events per batch
flushInterval: 10000, // Flush interval (ms)
timeout: 30000, // Request timeout (ms)
compression: true, // Enable gzip compression
});API
capture(options)
Capture an event.
signal.capture({
distinctId: 'user-123',
event: 'page_viewed',
properties: {
page: '/dashboard',
referrer: '/home',
},
timestamp: new Date(), // Optional
groups: { // Optional
company: 'acme-corp',
team: 'engineering',
},
});identify(options)
Identify a user.
signal.identify({
distinctId: 'user-123',
properties: {
email: '[email protected]',
name: 'John Doe',
createdAt: '2024-01-01',
},
});setPersonProperties(distinctId, properties)
Set user properties.
signal.setPersonProperties('user-123', {
plan: 'enterprise',
last_seen: new Date().toISOString(),
});setPersonPropertiesOnce(distinctId, properties)
Set user properties only if not already set.
signal.setPersonPropertiesOnce('user-123', {
first_seen: new Date().toISOString(),
});group(distinctId, groupType, groupKey, properties?)
Associate a user with a group.
signal.group('user-123', 'company', 'acme-corp', {
name: 'Acme Corp',
plan: 'enterprise',
employee_count: 500,
});groupIdentify(options)
Identify a group (set group properties).
signal.groupIdentify({
groupType: 'company',
groupKey: 'acme-corp',
properties: {
name: 'Acme Corp',
plan: 'enterprise',
},
});alias(distinctId, alias)
Create an alias for a user.
signal.alias('user-123', 'email:[email protected]');flush()
Flush all queued events immediately.
await signal.flush();shutdown()
Gracefully shutdown (flush remaining events).
await signal.shutdown();Edge Runtime Support
The package includes an edge-compatible build for Cloudflare Workers, Vercel Edge, etc.
// Automatic (runtime detection)
import { createSignalNode } from '@signal-js/node';
// Or explicit edge import
import { createSignalNode } from '@signal-js/node/edge';Usage Examples
Express.js
import express from 'express';
import { createSignalNode } from '@signal-js/node';
const app = express();
const signal = createSignalNode({
endpoint: process.env.SIGNAL_ENDPOINT!,
apiKey: process.env.SIGNAL_API_KEY!,
});
app.post('/api/checkout', async (req, res) => {
const { userId, amount, items } = req.body;
signal.capture({
distinctId: userId,
event: 'checkout_completed',
properties: { amount, item_count: items.length },
});
res.json({ success: true });
});
// Graceful shutdown
process.on('SIGTERM', async () => {
await signal.shutdown();
process.exit(0);
});Next.js API Routes
// pages/api/track.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { createSignalNode } from '@signal-js/node';
const signal = createSignalNode({
endpoint: process.env.SIGNAL_ENDPOINT!,
apiKey: process.env.SIGNAL_API_KEY!,
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
const { userId, event, properties } = req.body;
signal.capture({
distinctId: userId,
event,
properties,
});
res.status(200).json({ success: true });
}
}License
MIT
