Skip to main content
Signals implementation
Customer-facing AI agents

Build an AI agent with real-time user context using Signals and Vercel AI SDK

Build a Next.js AI agent that uses Snowplow Signals to deliver contextually aware responses based on live user behavior.

Progress0%

Implement Snowplow tracking in the Next.js app

Snowplow Signals computes user attributes from your Snowplow behavioral event stream. Follow these steps to create events to work with.

Signals doesn't need custom events: standard page views, page pings, and link clicks are enough to build meaningful real-time context.

Since you're building a Next.js app, you'll use the Snowplow Browser tracker, which is designed for npm-based frameworks.

Initialize the tracker

Create a module that initializes the Snowplow tracker once, and exports a helper to read the session ID. This module runs client-side only.

tsx
// lib/snowplow.ts
import {
newTracker,
trackPageView,
enableActivityTracking,
type BrowserTracker,
} from "@snowplow/browser-tracker";
import {
LinkClickTrackingPlugin,
enableLinkClickTracking,
} from "@snowplow/browser-plugin-link-click-tracking";

let tracker: BrowserTracker | null = null;

export function initSnowplow() {
if (tracker || typeof window === "undefined") return;

tracker = newTracker("sp", process.env.NEXT_PUBLIC_SNOWPLOW_COLLECTOR_URL!, {
appId: "signals-agent",
plugins: [LinkClickTrackingPlugin()],
}) ?? null;

enableActivityTracking({
minimumVisitLength: 30,
heartbeatDelay: 10,
});

enableLinkClickTracking({ pseudoClicks: true });
}

export function trackPage() {
trackPageView();
}

export function getDomainSessionId(): string {
if (!tracker) return "";
try {
// getDomainUserInfo() returns the _sp_id cookie as an array.
// Index [6] is the domain_sessionid.
const info = tracker.getDomainUserInfo();
return info?.[6] ?? "";
} catch {
return "";
}
}

The session ID is stored in the _sp_id cookie, which the getDomainUserInfo() method reads. You'll use this value later to fetch the current user's Signals attributes.

Track page views on route changes

In a Next.js App Router app, client-side navigation doesn't trigger full page reloads.

Create a client component to track page views when the route changes:

tsx
// components/snowplow-provider.tsx
"use client";

import { useEffect } from "react";
import { usePathname } from "next/navigation";
import { initSnowplow, trackPage } from "@/lib/snowplow";

export function SnowplowProvider({ children }: { children: React.ReactNode }) {
const pathname = usePathname();

// Initialize tracker on mount
useEffect(() => {
initSnowplow();
}, []);

// Track page view on every route change
useEffect(() => {
trackPage();
}, [pathname]);

return <>{children}</>;
}

The scaffolded app/layout.tsx already includes font imports, a lang attribute, and CSS classes. Add the SnowplowProvider import and wrap {children} with it:

tsx
// app/layout.tsx — add these two changes to your scaffolded layout:

// 1. Add this import at the top
import { SnowplowProvider } from "@/components/snowplow-provider";

// 2. Wrap {children} inside the <body> tag:
<body className={/* ...keep existing classes... */}>
<SnowplowProvider>{children}</SnowplowProvider>
</body>

With this in place, every route change fires a page view event, page pings track ongoing engagement, and link clicks are captured automatically. That gives Signals a rich behavioral event stream to compute attributes from.

On this page

Want to see a custom demo?

Our technical experts are here to help.