React
npm install https://api.3x.example/v1/sdk/3x-engine-sdk-0.1.0.tgz// src/main.tsx
import { createRoot } from "react-dom/client";
import { X3Provider } from "@3x-engine/sdk/react";
import { App } from "./App";
createRoot(document.getElementById("root")!).render(
<X3Provider options={{ key: import.meta.env.VITE_X3_KEY, host: "/n3" }}>
<App />
</X3Provider>,
);// anywhere below the provider
import { useX3 } from "@3x-engine/sdk/react";
export function PricingToggle() {
const x3 = useX3();
return <button onClick={() => x3.track("pricing_toggle", { period: "yearly" })}>Yearly</button>;
}X3Providercallsinitonce on mount. React StrictMode's unmount/remount in development does not split the pageview: stopping is deferred by a task and cancelled by the remount.- Routing needs no wiring: the History API patch reports React Router, TanStack Router and similar
navigations as
spapageviews. useX3()returns the same API as the npm package (SDK reference). Outside a provider it returns a no-op API, so components stay testable.
Without the provider
Calling init in your entry file and importing track where needed works just as well; the
provider only adds lifecycle handling and the hook.
Next.js
Use the dedicated adapter: Next.js.