Next.js SDK
App Router-native wiring for GetFluxly. Drop-in <GFluxScript> for client autocapture, server-side track / identify / alias for Server Actions and Route Handlers, and a middleware wrapper that forwards client IP and geo into downstream handlers.
Install
npm install @getfluxly/next @getfluxly/react @getfluxly/browser @getfluxly/node
react and next are peer dependencies already in your project. The four @getfluxly/* packages are peers too. Install them all so npm deduplicates the runtime.
Quickstart
1. Set env vars
Create or update .env.local at your project root:
# .env.local
NEXT_PUBLIC_GFLUX_API_KEY=gflux_pub_...
GFLUX_SERVER_TOKEN=gflux_secret_...
NEXT_PUBLIC_GFLUX_API_KEY is the publishable key, safe to expose to the browser. GFLUX_SERVER_TOKEN is the server key; never expose it client-side.
2. Mount GFluxScript in app/layout.tsx
import { GFluxScript } from "@getfluxly/next/client";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<GFluxScript apiKey={process.env.NEXT_PUBLIC_GFLUX_API_KEY!} />
{children}
</body>
</html>
);
}
That enables client-side autocapture (pageviews, clicks, forms, errors). Open the GetFluxly dashboard live feed and events arrive within a second.
Warning: Mount
<GFluxScript>or<GFluxProvider>, not both. Each constructs its own client, so mounting both sends every event twice.
3. Track from a Server Action (optional)
// app/actions/subscribe.ts
"use server";
import { track } from "@getfluxly/next/server";
export async function signUpAction(formData: FormData) {
const user = await createUser(formData);
await track("user_signed_up", {
externalId: user.id,
properties: { plan: user.plan },
});
return { ok: true };
}
The server helper flushes immediately, which is the right default for short-lived serverless invocations. For long-running servers, use getServerClient() and manage the lifecycle yourself.
Client: @getfluxly/next/client
GFluxScript
<GFluxScript> wraps next/script with strategy="afterInteractive" by default. Set strategy="lazyOnload" to defer past hydration.
| Prop | Type | Description |
|---|---|---|
apiKey | string | Publishable key (gflux_pub_*). Renders nothing when missing. |
apiHost | string | API base URL. Defaults to https://api.getfluxly.com. |
nonce | string | CSP nonce, passed through to <script>. |
strategy | "afterInteractive" | "lazyOnload" | next/script load strategy. Defaults to "afterInteractive". |
React hooks
@getfluxly/next/client re-exports all five React hooks from @getfluxly/react: useGFlux, useTrack, useIdentify, usePage, and useConsent. It also re-exports GFluxProvider if you prefer the React-state-based pattern instead of the script tag.
Server: @getfluxly/next/server
This subpath is gated to Node-only via the package exports map. Importing it from a client component fails the Next build with a server-only error, so your server token can never leak into the browser bundle.
getServerClient()
Returns the singleton @getfluxly/node client for the current process. It is cached on globalThis.__gflux_node__ so Next.js hot-reload does not leak background flush timers between module re-evaluations.
import { getServerClient } from "@getfluxly/next/server";
const client = getServerClient();
await client.track("invoice_paid", {
externalId: "user_42",
properties: { amount: 99 },
});
await client.flush();
track / identify / alias
Convenience helpers on top of the singleton. All three flush immediately.
import { track, identify, alias } from "@getfluxly/next/server";
await track("event_name", { externalId, properties });
await identify({ externalId, anonymousId, traits });
await alias({ userId, previousId });
| Helper | Required fields | Notes |
|---|---|---|
track(event, opts) | event string | opts.externalId or opts.anonymousId required |
identify(opts) | externalId or anonymousId | Merges traits into the user profile |
alias(opts) | userId, previousId | Stitches an anonymous ID into a known user |
Middleware: @getfluxly/next/middleware
withGFluxMiddleware
Wraps a Next.js middleware function and mutates request headers before calling your handler, so downstream Server Components and Route Handlers can read them.
// middleware.ts
import { withGFluxMiddleware } from "@getfluxly/next/middleware";
import { NextResponse } from "next/server";
export default withGFluxMiddleware(
async (request) => {
return NextResponse.next();
},
{ forwardIp: true, forwardGeo: true },
);
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
Headers added when the corresponding option is enabled:
| Header | Source | Default |
|---|---|---|
x-gflux-ip | request.ip or x-real-ip | Off |
x-gflux-country | request.geo.country | Off |
x-gflux-region | request.geo.region | Off |
Nothing is forwarded by default. Both forwardIp and forwardGeo are opt-in. Enable them only if you intend to enrich server-side track() calls with the client's network identity; forwarding changes the data semantics for downstream consumers.
gfluxEnv()
Type-safe reader for the three Next.js env vars. Use it in any server file to assert vars are present at startup rather than at first use.
import { gfluxEnv } from "@getfluxly/next";
const env = gfluxEnv({ requirePublicKey: true, requireServerToken: true });
// env.publicKey = NEXT_PUBLIC_GFLUX_API_KEY
// env.serverToken = GFLUX_SERVER_TOKEN
// env.apiHost = NEXT_PUBLIC_GFLUX_API_HOST (optional, has default)
| Option | Behavior |
|---|---|
requirePublicKey | Throws if NEXT_PUBLIC_GFLUX_API_KEY is missing. Names the variable in the error message. |
requireServerToken | Throws if GFLUX_SERVER_TOKEN is missing. Names the variable in the error message. |
Error handling
Browser hooks (useTrack, usePage, etc.) are fire-and-forget. They never throw to caller code; a failed delivery is silently retried or dropped, keeping your UI unaffected.
Server helpers throw GFluxNodeError on failure. Wrap server-side calls in try/catch if you need to handle delivery failures explicitly:
import { track, GFluxNodeError } from "@getfluxly/next/server";
try {
await track("checkout_completed", { externalId: userId, properties: { total } });
} catch (err) {
if (err instanceof GFluxNodeError) {
// log err.code, err.status, err.retryable
}
}
Required env vars
| Variable | Where | Notes |
|---|---|---|
NEXT_PUBLIC_GFLUX_API_KEY | Client + server | Publishable key |
GFLUX_SERVER_TOKEN | Server only | Never expose to the browser |
NEXT_PUBLIC_GFLUX_API_HOST | Optional | Defaults to https://api.getfluxly.com |