Skip to content
Docs menu Websites

React and Next.js

One provider near the root, a hook to send events, and a page view on every route change

On this page

The React bindings ship inside the npm package as @sfere.io/sfere-sdk/react. React 17 or newer is supported. Use the bindings or the script-tag loader on a page, not both: each loads its own copy and every event would be sent twice.

Install#

Shell
npm install @sfere.io/sfere-sdk

Add the provider#

SfereProvider loads the SDK once per write key and host for the life of the page, including under StrictMode and hot reload.

Hook What it does
useSfere() Returns the SDK instance: track, identify, page, reset, setConsent and more.
usePageTracking(routeKey) Sends one page() each time routeKey changes.

Examples#

App.tsxTSX
import { useLocation } from "react-router-dom";
import { SfereProvider, usePageTracking, useSfere } from "@sfere.io/sfere-sdk/react";

function PageViews() {
  const { pathname, search } = useLocation();
  usePageTracking(pathname + search);
  return null;
}

export default function App() {
  return (
    <SfereProvider writeKey="YOUR_WRITE_KEY" host="https://events.sfere.io">
      <PageViews />
      {/* your routes */}
    </SfereProvider>
  );
}

function AddToCartButton({ item }) {
  const sfere = useSfere();
  return (
    <button onClick={() => sfere.track("add_to_cart", { currency: "USD", value: item.price, items: [item] })}>
      Add to cart
    </button>
  );
}

Create a client component for the provider and render it from app/layout.tsx. useSearchParams() needs a Suspense boundary.

app/providers.tsxTSX
"use client";
import { Suspense } from "react";
import { usePathname, useSearchParams } from "next/navigation";
import { SfereProvider, usePageTracking } from "@sfere.io/sfere-sdk/react";

function PageViews() {
  const pathname = usePathname();
  const search = useSearchParams().toString();
  usePageTracking(search ? `${pathname}?${search}` : pathname);
  return null;
}

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <SfereProvider
      writeKey={process.env.NEXT_PUBLIC_SFERE_WRITE_KEY!}
      host="https://events.sfere.io"
    >
      <Suspense fallback={null}><PageViews /></Suspense>
      {children}
    </SfereProvider>
  );
}
pages/_app.tsxTSX
import type { AppProps } from "next/app";
import { useRouter } from "next/router";
import { SfereProvider, usePageTracking } from "@sfere.io/sfere-sdk/react";

function PageViews() {
  usePageTracking(useRouter().asPath);
  return null;
}

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <SfereProvider writeKey={process.env.NEXT_PUBLIC_SFERE_WRITE_KEY!} host="https://events.sfere.io">
      <PageViews />
      <Component {...pageProps} />
    </SfereProvider>
  );
}

Server rendering#

During server rendering the provider returns an inert instance whose methods do nothing, so nothing is sent from the server and shared components can call useSfere() safely.

Options#

The provider accepts every load() option, plus disabled to turn tracking off (for example in tests). Options other than writeKey and host are read once, when the provider first mounts.