atrixANALYTICS
SDKs

React

Use the web SDK in React, Next.js and other React frameworks.

No separate React package yet

A dedicated @atrix.dev/analytics-react package with a provider and hooks is planned. Today React apps use @atrix.dev/analytics-web directly, which is SSR-safe: every call is a no-op on the server. The patterns below are all you need.

npm i @atrix.dev/analytics-web

Initialise once

Call init once on the client, as early as you can. On the server it does nothing, so it is safe to call from a module that is also rendered on the server.

"use client";

import * as atrix from "@atrix.dev/analytics-web";
import { type ReactNode, useEffect } from "react";

export function AnalyticsProvider({ children }: { children: ReactNode }) {
  useEffect(() => {
    atrix.init("atx_pk_eu_production_XXXXXXXXXXXXXXXXXXXXXX", { replay: { sampleRate: 0.2 } });
    return () => void atrix.shutdown();
  }, []);
  return <>{children}</>;
}

In the Next.js App Router, render <AnalyticsProvider> in your root layout. Pageviews for client-side navigations are recorded automatically from the History API, so you do not need a router hook.

Identify on sign-in, reset on sign-out

import * as atrix from "@atrix.dev/analytics-web";
import { useEffect } from "react";

export function useIdentify(user: { id: string; plan: string } | null) {
  useEffect(() => {
    if (user) atrix.identify(user.id, { plan: user.plan });
  }, [user]);
}

export function signOut() {
  atrix.reset();
}

A flag hook

onFlags calls back immediately when values are known and again after every reload, and returns an unsubscribe function, which fits useSyncExternalStore:

import * as atrix from "@atrix.dev/analytics-web";
import { useSyncExternalStore } from "react";

export function useFlag(key: string): boolean {
  return useSyncExternalStore(
    (onChange) => atrix.onFlags(onChange),
    () => atrix.isEnabled(key),
    () => false,
  );
}

export function useVariant(key: string): string | null {
  return useSyncExternalStore(
    (onChange) => atrix.onFlags(onChange),
    () => atrix.getVariant(key),
    () => null,
  );
}
import { useFlag } from "./flags";

export function Checkout() {
  const newCheckout = useFlag("new-checkout");
  return newCheckout ? <p>New checkout</p> : <p>Classic checkout</p>;
}

To avoid a flicker on first render, pass values you already know (for example from your server) as bootstrap: { flags: { … } } to init.

Tracking from components

Call atrix.track from event handlers. Keep event names stable and in snake_case, and send money as integer minor units:

import * as atrix from "@atrix.dev/analytics-web";

export function BuyButton({ priceMinor }: { priceMinor: number }) {
  return (
    <button type="button" onClick={() => atrix.track("buy_clicked", { amount: priceMinor, currency: "USD" })}>
      Buy
    </button>
  );
}

Everything else, including options, consent and replay masking, is in the web SDK guide.

On this page