Documentation

Analytics SDK

@vantrex/analytics has a browser part, a server part and a Next.js component. This is how to use each.

Install

npm install @vantrex/analytics

The package has three entry points: @vantrex/analytics/client for the browser, @vantrex/analytics/server for your server, and @vantrex/analytics/next for a ready-made Next.js component. It needs Node 18 or newer.

In the browser

In Next.js, add the component once to your root layout. It reads NEXT_PUBLIC_VANTREX_ANALYTICS_KEY.

app/layout.tsx
import { VantrexAnalytics } from "@vantrex/analytics/next";

export default function Layout({ children }) {
  return (
    <html>
      <body>
        {children}
        <VantrexAnalytics />
      </body>
    </html>
  );
}

In any other framework, start it yourself:

import { init, track } from "@vantrex/analytics/client";

init({ publishableKey: "vtxa_pk_…" });

track("checkout_clicked", { plan: "pro" });

Any element with a data-vtx-track attribute is counted when it is clicked:

<button data-vtx-track="start_trial">Start your trial</button>

While a tab is visible the browser sends a small heartbeat every 20 seconds. That is what the Active users page shows. A first-party cookie, vtxa_vid, holds a random visitor ID for the length of the browser session; the server part uses it to connect a sign-in to the tab the person has open.

On your server

lib/analytics.ts
import { createAnalytics } from "@vantrex/analytics/server";

export const analytics = createAnalytics(); // reads VANTREX_ANALYTICS_SECRET

Then report outcomes from the code that handles them. Pass the incoming request so Vantrex gets the visitor's country and browser and can link the person to their tab.

// a successful sign-in
await analytics.trackLogin({ userId: user.id, email: user.email, name: user.name, request });

// a failed one
await analytics.trackLogin({ userId: "", ok: false, errorCode: "bad_password", request });

// a sign-up, with how long it took
const took = analytics.timer();
const user = await createAccount(form);
await analytics.trackSignup({ userId: user.id, email: user.email, request, durationMs: took() });

// anything else you want counted
await analytics.track("purchase", { amount: 4900 });

Only the details your project collects are stored. If you did not choose to collect email, the email you pass is dropped on arrival.

With Better Auth

If you use Better Auth, one hook reports sign-ins, sign-ups and failures for you:

import { betterAuth } from "better-auth";
import { createAuthMiddleware } from "better-auth/api";
import { betterAuthAfterHook } from "@vantrex/analytics/server";
import { analytics } from "./analytics";

export const auth = betterAuth({
  hooks: { after: createAuthMiddleware(betterAuthAfterHook(analytics)) },
});

For another sign-in library, call trackLogin and trackSignup from its success and failure callbacks.

Serverless and delivery

Each call returns a promise that never rejects. A failed delivery is retried once and then reported to the onError function if you gave one; it never throws into your sign-in code. On serverless platforms, await the call so the function does not end before the event is sent.

const analytics = createAnalytics({
  onError: (err) => console.warn("analytics:", err.message),
});

From the browser, events are sent with sendBeacon or a keep-alive request so they survive the page closing. Browsers do not guarantee delivery when a page is being unloaded, so a few clicks and the last heartbeat of a visit can be missed.

Reference

Browser

FunctionWhat it does
init(options)Starts heartbeats and click tracking. Safe to call twice and does nothing on the server. Options: publishableKey, endpoint, heartbeatMs (default 20000), autoClicks (default true), deploymentId.
track(name, props?)Records a click or other interaction.

Server

FunctionWhat it does
createAnalytics(options?)Options: secretKey, endpoint, deploymentId, onError, timeoutMs (default 3000).
trackLogin(event)userId, and optionally name, email, request, ip, userAgent, visitorId, ok, errorCode, durationMs, props.
trackSignup(event)The same fields as trackLogin.
identify(subject)Tells Vantrex who a visitor is, for the Active users page.
track(name, props?, subject?)Records a named event from the server.
timer()Returns a function that gives the milliseconds since it was created.

If your app runs on Vantrex, the deployment ID is read from NEXT_PUBLIC_VTX_DEPLOYMENT_ID or VTX_DEPLOYMENT_ID when they are set, which is what the deployment filter uses. You can also pass deploymentId yourself.