Next.js
Looking for a step-by-step tutorial? Check out the Next.js analytics guide.
Good to know
All client-side tracking runs in the browser. For server-side event tracking, see the Server Side Tracking section below.
Installation
Install dependencies
pnpm install @helionlabs/nextjsInitialize
Add HelionComponent to your root layout component.
import { HelionComponent } from '@helionlabs/nextjs';
export default function RootLayout({ children }) {
return (
<>
<HelionComponent
clientId="your-client-id"
trackScreenViews={true}
// trackAttributes={true}
// trackOutgoingLinks={true}
// If you have a user id, you can pass it here to identify the user
// profileId={'123'}
/>
{children}
</>
)
}Options
Common options
apiUrl- The url of the helion API or your self-hosted instanceclientId- The client id of your applicationclientSecret- The client secret of your application (only required for server-side events)filter- A function that will be called before sending an event. If it returns false, the event will not be sentdisabled- If true, the library will not send any events
Web options
trackScreenViews- If true, the library will automatically track screen views (default: false)trackOutgoingLinks- If true, the library will automatically track outgoing links (default: false)trackAttributes- If true, you can trigger events by using html attributes (<button type="button" data-track="your_event" />) (default: false)sessionReplay- Session replay configuration object (default: disabled). See session replay docs for full options.enabled- Enable session replay recording (default: false)maskAllInputs- Mask all input field values (default: true)maskTextSelector- CSS selector for text elements to mask (default:[data-helion-replay-mask])blockSelector- CSS selector for elements to replace with a placeholder (default:[data-helion-replay-block])blockClass- Class name that blocks elements from being recordedignoreSelector- CSS selector for elements excluded from interaction trackingflushIntervalMs- How often (ms) recorded events are sent to the server (default: 10000)maxEventsPerChunk- Maximum events per payload chunk (default: 200)maxPayloadBytes- Maximum payload size in bytes (default: 1048576)scriptUrl- Custom URL for the replay script (script-tag builds only)
Next.js options
profileId— If you have a user ID, pass it here to identify the user automaticallycdnUrl(deprecated) — The URL to the Helion SDK (default:https://helionlabs.dev/hl1.js)scriptUrl— The URL to the Helion SDK (default:https://helionlabs.dev/hl1.js)filter— A function called before each event. Returnfalseto suppress the event. Read moreglobalProperties— Properties sent with every event
filter
The filter must be a stringified function and cannot reference variables outside of its own scope.
<HelionComponent
clientId="your-client-id"
filter={`
function filter(event) {
return event.name !== 'my_event';
}
`}
/>To take advantage of TypeScript, use .toString():
import { type TrackHandlerPayload } from '@helionlabs/nextjs';
const helionFilter = ((event: TrackHandlerPayload) => {
return event.type === 'track' && event.payload.name === 'my_event';
}).toString();
<HelionComponent
clientId="your-client-id"
filter={helionFilter}
/>Usage
Client components
Use the useHelion hook in client components:
import { useHelion } from '@helionlabs/nextjs';
function YourComponent() {
const hl = useHelion();
return <button type="button" onClick={() => hl.track('my_event', { foo: 'bar' })}>Trigger event</button>
}Server components
Hooks are not available in server components. Create a shared Helion instance and import it where needed:
import { Helion } from '@helionlabs/nextjs';
export const hl = new Helion({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
});Refer to the JavaScript SDK for usage instructions.
Tracking Events
Call hl.track() directly, or use data-track attributes on HTML elements for automatic click tracking.
useHelion().track('my_event', { foo: 'bar' });Identifying Users
Call hl.identify() with a unique identifier to associate the session with a known user profile.
useHelion().identify({
profileId: '123', // Required
firstName: 'Joe',
lastName: 'Doe',
email: 'joe@doe.com',
properties: {
tier: 'premium',
},
});For server components
Use the IdentifyComponent exported from @helionlabs/nextjs when user data is available server-side:
import { IdentifyComponent } from '@helionlabs/nextjs';
export default function Layout({ children }) {
const user = await getCurrentUser()
return (
<>
<IdentifyComponent
profileId={user.id}
firstName={user.firstName}
lastName={user.lastName}
email={user.email}
properties={{
tier: 'premium',
}}
/>
{children}
</>
)
}Setting Global Properties
Properties set via setGlobalProperties are attached to every subsequent event.
useHelion().setGlobalProperties({
app_version: '1.0.2',
environment: 'production',
});Incrementing Properties
Increment a numeric property on a user profile. Omit value to increment by 1.
useHelion().increment({
profileId: '1',
property: 'visits',
value: 1 // optional
});Decrementing Properties
Decrement a numeric property on a user profile. Omit value to decrement by 1.
useHelion().decrement({
profileId: '1',
property: 'visits',
value: 1 // optional
});Working with Groups
Groups let you track analytics at the account or company level. See the Groups guide for the full walkthrough.
Create or update a group:
useHelion().upsertGroup({
id: 'org_acme',
type: 'company',
name: 'Acme Inc',
properties: { plan: 'enterprise' },
});Assign the current user to a group (call after identify):
useHelion().setGroup('org_acme');Once set, all subsequent track() calls will automatically include the group IDs.
Clearing User Data
clear() resets the profile, device identity, session, and all group associations. Call it on logout.
useHelion().clear()Server side
To track server-side events, use the HelionSdk class exported from @helionlabs/nextjs.
Server-side tracking requires a client secret to authenticate requests. The secret prevents unauthorized event ingestion because CORS headers cannot protect server-to-server calls.
You can reuse the same clientId but must supply the associated clientSecret.
import { HelionSdk } from '@helionlabs/nextjs';
const hlServer = new HelionSdk({
clientId: '{YOUR_CLIENT_ID}',
clientSecret: '{YOUR_CLIENT_SECRET}',
});
hlServer.event('my_server_event', { ok: true });
// Pass `profileId` to attribute the event to a specific user
hlServer.event('my_server_event', { profileId: '123', ok: true });Serverless & Vercel
In serverless environments like Vercel, use waitUntil to ensure the event is logged before the function terminates:
import { waitUntil } from '@vercel/functions';
import { hlServer } from 'path/to/your-sdk-instance';
export function GET() {
waitUntil(hlServer.event('my_server_event', { foo: 'bar' }));
return new Response(`Your event has been logged!`);
}Proxy events
Use createRouteHandler to proxy tracking requests through your own server, bypassing adblockers that block third-party domains. The handler routes requests based on path, supporting API endpoints (/track, /track/device-id) and the tracking script (/hl1.js).
import { createRouteHandler } from '@helionlabs/nextjs/server';
export const { GET, POST } = createRouteHandler();Update HelionComponent to point at your proxy:
<HelionComponent
apiUrl="/api/hl"
scriptUrl="/api/hl/hl1.js"
clientId="your-client-id"
trackScreenViews={true}
/>