@kissmetrics/node
v1.1.2
Published
Kissmetrics server-side event tracking for Node.js. Record events, set people properties, and alias identities from your backend.
Maintainers
Readme
@kissmetrics/node
Server-side Kissmetrics tracking for Node.js. Record events, set people properties, and identify people straight from your backend, where the data is trusted (can't be spoofed by the browser) and isn't blocked by ad-blockers. No client SDK required.
The model is small: every call takes a person (who) and, for events, an event name (what they did). An optional properties object describes that person or event so you can break reports down later. That's the whole API.
Requirements
- Node 18 or newer. Check with
node --version. - Your Kissmetrics product key: the same key your web snippet uses, found in your product's settings in Kissmetrics. (The browser and server packages share one key and report into the same product.)
Install
npm install @kissmetrics/nodeQuick start
const KM = require("@kissmetrics/node")("YOUR_PRODUCT_KEY");
// Record an event: who (an email or your own user id) and what they did.
await KM.record("[email protected]", "Signed Up");
// Record a pageview (the "Viewed Page" event) so server-side views line up with
// the web snippet's pageviews. Use Current Page / Previous Page / URL to match
// the property names the web snippet sends.
await KM.pageview("[email protected]", { "Current Page": "/pricing", "Previous Page": "/home" });
// Set a property on the PERSON (their current state, not tied to one event).
await KM.set("[email protected]", { plan: "pro" });
// Identify: connect an anonymous web visitor to the real person at login/signup.
await KM.identify("anon-abc123", "[email protected]");Using ES modules or TypeScript instead of require:
import KISSmetrics from "@kissmetrics/node";
const km = KISSmetrics("YOUR_PRODUCT_KEY");
await km.record("[email protected]", "Signed Up", { plan: "pro" });Every name and value in this README (
"Signed Up","Purchased",plan,amount: 49,[email protected], …) is just demo data showing the shape of a call. Swap in the events, properties, and ids that match your own product.
Event properties
The optional third argument to record is a properties object describing
that event. Properties are how you slice reports afterwards:
// "plan" and "amount" describe THIS purchase. Later you can report revenue, or
// break "Purchased" down by plan, without a separate event for each.
await KM.record("[email protected]", "Purchased", { plan: "pro", amount: 49 });Pass only values you actually have; skip a property rather than send a
placeholder or a guess. Nullish values (null / undefined) are dropped for
you, and the reserved keys (_k / _p / _n / _t / _d) can't be
overwritten.
Recording events
record(person, event, properties?) is the one primitive. There's no
autocapture on the server (no DOM to watch), so you record the meaningful
actions where they happen: a signup, a purchase, a form handler, a webhook, a
job.
// in your API route / controller / job. userId and selectedPlan come from your
// app (the logged-in user, the plan they chose), not hardcoded literals:
await km.record(userId, "Subscribed", { plan: selectedPlan });pageview() is just sugar over record(person, "Viewed Page", properties). Pass
Current Page, Previous Page, and URL so your server-side and client-side
pageviews use the same property names and line up in one report.
Identifying people
A visitor is usually anonymous first: before they log in, the web snippet
(@kissmetrics/install) tracks them in the browser under a random anonymous
id it generates for them. When they sign up or log in, you connect that
anonymous id to their real identity (an email, or your own user id) so their
before-and-after history becomes one person.
Where do I get the anonymous id?
It lives in the browser, created by the web snippet, so your server doesn't know it until the browser sends it over. Read it on the client and include it in your sign-up / log-in request:
// In the browser, as the user submits sign-up / log-in.
// KM.i() returns the visitor's current id: their known id if they already have
// one, otherwise the anonymous id the snippet generated (kept in the `km_ai`
// cookie). At first sign-up that's the anonymous id, which is what you want.
const anonymousId = window.KM ? KM.i() : null;
await fetch("/signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, anonymousId }),
});Then, in your server handler, tie the two ids together. Call this once, at sign-up or log-in:
// On the server, in your sign-up / log-in route.
await km.identify(anonymousId, "[email protected]");After that, just record against the real identity. You don't need identify
again once you already know who the person is:
await km.record("[email protected]", "Purchased", { plan: "pro", amount: 49 });alias is for the rarer case of merging two already-known identities into one
(an email change, or two accounts you've found are the same person). Reach for
identify for everyday anonymous-to-known linking, and alias only when both
ids are real. Direction matters: alias(fromId, toId) merges fromId into
toId, and toId survives as the canonical identity.
// Same person, changed their email: merge the old id into the new one.
await km.alias("[email protected]", "[email protected]");Check that it's reaching Kissmetrics
Fire your first event from your backend (the quick-start snippet above), then confirm Kissmetrics received it. If you're setting Kissmetrics up for the first time, the onboarding screen shows a Verify installation button that turns green the moment your first event arrives.
Client options
You only ever have to pass your product key, e.g.
const km = require("@kissmetrics/node")("YOUR_PRODUCT_KEY"). If it's missing,
the client throws right away (the one and only place this library throws).
Everything else is optional, and the defaults are right for normal use, so reach
for these only if you have a specific reason:
onError: a function called when an event fails to send (a network error or a timeout). Because the SDK never throws, this is how you'd log those failures. Ignored by default.timeout: how long to wait for the tracking server before giving up, in milliseconds. Default10000(10 seconds).baseUrl: where events are sent. Defaults to the Kissmetrics production server; set it only to point at a staging server or a proxy. It can also come from theKM_TRACKING_BASE_URLenvironment variable.
// Example: log delivery failures instead of ignoring them.
const km = KISSmetrics("YOUR_PRODUCT_KEY", {
onError: (err) => console.error("kissmetrics:", err.message),
});The tracking methods (record, pageview, set, identify, alias) never
throw. Each returns a Promise<boolean> that resolves true when the tracking
server accepted the event and false otherwise (including a missing
person/event, or set with no properties), so a failed send can't crash your
app. Awaiting is optional: in a long-running server you can fire-and-forget and
skip the await.
⚠️ Serverless: you must
await. On Lambda, Vercel, Cloudflare Workers, Netlify Functions, and similar, the runtime freezes or kills the process the moment you return the response — any tracking request still in flight is silently dropped. In these environments alwaysawaitevery KM call (orPromise.all([...])them) before returning, or use the platform's "wait until"/background hooks (e.g.waitUntil). Fire-and-forget only reaches the server in a process that keeps running after the response.
Failure diagnostics
If your events never reach Kissmetrics (no delivery succeeds after a few tries in a row, with none having ever succeeded), the client does two things once:
- Logs a short recovery checklist to your console (check the key, check network, or install another way).
- Sends one anonymous diagnostic to Kissmetrics so we can see broken installs.
The moment any event is accepted, this is switched off for good. The diagnostic never includes your product key, your event data, people data, or your hostname: only the error kind, this package's version, your Node version, and your OS.
Turn it off with telemetry: false, or the KM_DISABLE_TELEMETRY=1 /
DO_NOT_TRACK=1 environment variables. The recovery checklist still prints.
const km = KISSmetrics("YOUR_PRODUCT_KEY", { telemetry: false });Privacy & consent
This SDK sends exactly the events and properties you pass it — you decide what leaves your server. If you operate under GDPR, ePrivacy, CCPA, or similar, make sure you have a lawful basis / the visitor's consent before you identify them or record their activity, and avoid putting personal data in property values unless you need it. Kissmetrics is a data processor for the events you send; establishing consent and the lawful basis is the sender's responsibility.
Local development
Working on the package itself? Install it straight from the folder (or a packed tarball) into a test project:
npm install /path/to/km-npm-installer
# or: cd km-npm-installer && npm pack -> npm install /abs/path/kissmetrics-node-1.1.0.tgzFrom there, use it exactly as shown above. To confirm it's wired up, fire one event with your product key:
node -e "require('@kissmetrics/node')('<your-product-key>').record('[email protected]', 'Test Event').then(ok => console.log('accepted:', ok))"It prints accepted: true once the Kissmetrics tracking server has received the
event.
