JavaScript / TypeScript SDK
The Hintway JS/TS SDK is a lightweight, isomorphic library for sending analytics events to the Hintway platform from any JavaScript runtime: Node.js, modern browsers, and edge runtimes. It is a faithful port of the Go SDK, sharing the same wire format, endpoints, and behavior.
npm: @hintway/sdk
GitHub: hintwayapp/Javascript-SDK
Supported features:
- Immediate and batched event tracking
- Automatic retry when the server becomes available
- Persistent device and session identification (file-based in Node,
localStoragein browsers) - Verbose logging for debugging
- Full TypeScript types out of the box
- Zero runtime dependencies
Installation
Section titled “Installation”npm install @hintway/sdk# orpnpm add @hintway/sdk# oryarn add @hintway/sdkRequirements: Node.js 18+ (for native fetch). All modern browsers and edge runtimes are supported.
Initialization
Section titled “Initialization”Call init() once in your application’s entry point before sending any events.
import { Hintway } from '@hintway/sdk';
// Get the singleton instanceconst hintway = Hintway.instance();
// Optional: see network requests in the consolehintway.setVerbose(true);
hintway.init({ tenantId: '481b9cfb-4b48-4d99-a310-d383c6cc5d3b', serverUrl: 'https://in.hintway.app', platform: 'my_backend_service', appVersion: '1.0.0', autoBatching: true, // queue events and flush periodically flushIntervalSec: 2, // flush every 2 seconds});
// Give background tenant validation a moment to completeawait new Promise((r) => setTimeout(r, 1000));
// ... your app logic ...
await hintway.shutdown();Parameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
tenantId | string | — | Required. Your project identifier from the Hintway dashboard |
serverUrl | string | https://in.hintway.app | Server endpoint |
platform | string | — | Required. Free-form platform identifier, e.g. web_app, node_backend |
appVersion | string | 1.0.0 | Your application version |
autoBatching | boolean | — | Required. Queue events and flush on an interval instead of sending immediately |
flushIntervalSec | number | 10 | Flush interval in seconds (only used when autoBatching is true) |
What happens on initialization
Section titled “What happens on initialization”- Loads or generates a persistent device identifier
- Node: stored in
analytics.idnext toprocess.cwd() - Browser: stored in
localStorageunderhintway.analytics.id - Edge runtimes: in-memory only (regenerated on cold start unless you provide a custom storage adapter)
- Node: stored in
- Creates a new session ID
- Starts a background task to validate the tenant and check server health
- Enables or disables analytics based on server availability
If the server is unreachable, events are safely queued until connectivity is restored.
Tracking events
Section titled “Tracking events”Simple event
Section titled “Simple event”hintway.trackEvent('app_started');Event with string payload
Section titled “Event with string payload”hintway.trackEvent('user_logged_in', 'admin_user');Event with structured data
Section titled “Event with structured data”hintway.trackEvent('order_completed', { order_id: 12345, total_amount: 99.99, currency: 'USD', items_count: 3,});Batching
Section titled “Batching”Manual batching
Section titled “Manual batching”Use manual batching when you want explicit control over when events are sent (e.g. at the end of a transaction or an API request).
// Queue eventshintway.batchedTrackEvent('transaction_started', 'checkout');hintway.batchedTrackEvent('payment_processed', { amount: 49.99, method: 'credit_card', status: 'success',});
// Send all queued events in a single HTTP requesthintway.flushManualBatch();Automatic batching
Section titled “Automatic batching”Enable autoBatching: true during init():
trackEventcalls are queued automatically- The queue flushes every
flushIntervalSecseconds - If the server is unreachable, events stay queued until connectivity is restored
Custom data
Section titled “Custom data”Attach persistent metadata to every event the SDK sends — useful for user context, environment details, or any session-level information.
// Set custom data — included in all subsequent eventshintway.setCustomData({ user_id: 'user_123', subscription: 'premium', environment: 'production', region: 'us-east-1',});
hintway.trackEvent('feature_used', 'dark_mode_toggle');
// Remove custom datahintway.clearCustomData();// Or:hintway.setCustomData(null);- Custom data persists across event calls until explicitly cleared or replaced
- Empty / null custom data is not included in request payloads
- Non-serializable values are silently dropped (mirrors the Go SDK)
Lifecycle handling
Section titled “Lifecycle handling”Always call shutdown() before your application exits. It cancels background timers, drains any remaining queued events into a final batch, appends an app_exit event, and best-effort-flushes the result with a 2-second hard timeout.
Node script
Section titled “Node script”import { Hintway } from '@hintway/sdk';
async function main() { const hintway = Hintway.instance(); hintway.init({ tenantId: 'tenant-id', serverUrl: 'https://in.hintway.app', platform: 'cli_app', appVersion: '1.0.0', autoBatching: true, flushIntervalSec: 5, });
hintway.trackEvent('app_started'); // ... application logic ... hintway.trackEvent('app_completed');
await hintway.shutdown();}
main();Express / HTTP server
Section titled “Express / HTTP server”import express from 'express';import { Hintway } from '@hintway/sdk';
const hintway = Hintway.instance();hintway.init({ tenantId: 'tenant-id', platform: 'web_service', appVersion: '1.0.0', autoBatching: true, flushIntervalSec: 10,});
const app = express();
app.use((req, _res, next) => { hintway.trackEvent('api_request', { path: req.path, method: req.method }); next();});
// Flush on graceful shutdownasync function gracefulShutdown() { await hintway.shutdown(); process.exit(0);}process.on('SIGTERM', gracefulShutdown);process.on('SIGINT', gracefulShutdown);Browser (SPA)
Section titled “Browser (SPA)”import { Hintway } from '@hintway/sdk';
const hintway = Hintway.instance();hintway.init({ tenantId: 'tenant-id', platform: 'web_app', appVersion: '1.0.0', autoBatching: true, flushIntervalSec: 5,});
hintway.trackEvent('page_view', { path: window.location.pathname });
// Flush whatever is queued before the user leaveswindow.addEventListener('beforeunload', () => { hintway.flushManualBatch();});Edge runtime (Cloudflare Workers / Vercel Edge)
Section titled “Edge runtime (Cloudflare Workers / Vercel Edge)”import { Hintway } from '@hintway/sdk';
export default { async fetch(request: Request): Promise<Response> { const hintway = Hintway.instance(); hintway.init({ tenantId: 'tenant-id', platform: 'edge_worker', autoBatching: false, // requests are short — send immediately });
hintway.trackEvent('edge_request', { path: new URL(request.url).pathname });
// shutdown() ensures the final flush happens before the request ends await hintway.shutdown(); return new Response('ok'); },};