Activate Insights

Activating Insights takes two steps: generate a tracking token for your project, then register the tracking plugin in your front-end application.

Prerequisites

  • A Uniform project with Insights enabled. Contact support or your Uniform account representative if the Insights settings page is not available.
  • The Manage insights permission, which team admins have by default.
  • An application that renders Uniform compositions using Uniform Context.
  1. Open the project you want to enable Insights for.

  2. Go to Settings > Insights.

  3. Click Generate Tokens.

    note

    The tracking token can only append events. It cannot read your analytics data, so it is safe to ship to the browser.

  4. Use Copy as .env (Next.js) to copy the token, your project ID, and the tracking host as environment variables. The dropdown next to the button offers a variant without the NEXT_PUBLIC_ prefix for non-Next.js frameworks.

npm i @uniformdev/insights

Find the code that creates your Context instance, often a createUniformContext function, and add the Insights plugin to its plugin list.

The plugin only runs in the browser, so guard the registration to avoid constructing it during server rendering.

createUniformContext.ts

import { Context, ContextPlugin } from '@uniformdev/context' import { createInsightsPlugin } from '@uniformdev/insights' export function createUniformContext() { const plugins: ContextPlugin[] = [] if (typeof window !== 'undefined' && window.document) { plugins.push( createInsightsPlugin({ endpoint: { type: 'api', projectId: process.env.NEXT_PUBLIC_UNIFORM_PROJECT_ID!, apiKey: process.env.NEXT_PUBLIC_UNIFORM_INSIGHTS_API_KEY!, host: process.env.NEXT_PUBLIC_UNIFORM_INSIGHTS_API_URL!, }, }) ) } return new Context({ manifest, plugins }) }

Import from the right package

enableUniformInsights was removed from @uniformdev/context in version 20.81.0. That export was the plugin for the original Insights integration and sent data to a different destination. Import the plugin from @uniformdev/insights.

Within @uniformdev/insights, enableUniformInsights remains an alias of createInsightsPlugin for backward compatibility. Both work; new code should use createInsightsPlugin.

Paste the values you copied from Settings > Insights into your .env file.

.env
NEXT_PUBLIC_UNIFORM_INSIGHTS_API_KEY=<your-tracking-token> NEXT_PUBLIC_UNIFORM_PROJECT_ID=<your-project-id> NEXT_PUBLIC_UNIFORM_INSIGHTS_API_URL=<your-tracking-host>
.env
UNIFORM_PROJECT_ID=<your-project-id> UNIFORM_INSIGHTS_API_URL=<your-tracking-host> UNIFORM_INSIGHTS_API_KEY=<your-tracking-token>

The tracking host depends on the region your project is in.

For the North America region the host is https://analytics.uniform.global.

Always use the value shown on the settings page rather than hardcoding one, so the host follows the project.

Out of the box, events are attributed by URL. Passing a small amount of extra data lets Insights attribute them to the specific composition that rendered, and adds dynamic input values as a dimension you can filter and group by. This is what makes dynamic compositions, where many URLs resolve to one composition, report as a single page rather than a long tail of paths.

Pass matchedRoute and dynamicInputs into <UniformComposition>.

[[...path]].tsx

const Page: UniformCompositionNextPage = ({ data, matchedRoute, dynamicInputs }) => { const enhance = createUniformApiEnhancer({ apiUrl: '/api/preview' }) useSetViewportQuirk() return ( <UniformComposition data={data} contextualEditingEnhancer={enhance} behaviorTracking="onLoad" matchedRoute={matchedRoute} dynamicInputs={dynamicInputs} /> ) }

Pass the route resolution result into <UniformContext>.

page.tsx

// ./page.tsx export default async function UniformPage(props: UniformPageParameters) { const { code } = await props.params; return ( <UniformComposition code={code} resolveRoute={resolveRouteFromCode} resolveComponent={resolveComponent} clientContextComponent={CustomUniformClientContext} /> ); } // ./CustomUniformClientContext.tsx export const CustomUniformClientContext: ClientContextComponent = ({ manifest, defaultConsent, compositionMetadata, }) => { const router = useRouter(); useInitUniformContext(() => { const plugins: ContextPlugin[] = [ enableUniformInsights({ endpoint: { type: "api", projectId: process.env.NEXT_PUBLIC_UNIFORM_PROJECT_ID!, apiKey: process.env.NEXT_PUBLIC_UNIFORM_INSIGHTS_API_KEY!, host: process.env.NEXT_PUBLIC_UNIFORM_INSIGHTS_API_URL!, }, }), ]; return createClientUniformContext({ manifest, plugins, defaultConsent, }); }, compositionMetadata); return null; };

note

If your setup does not match either of these, Insights still works. Events are attributed by pathname instead of composition. Contact support if you need help wiring up composition attribution.

After deploying, confirm events are being sent.

  1. Confirm the app is configured: the environment variables are present at runtime, the plugin is registered in your Context initialization, and you are testing a page that renders a Uniform composition.

  2. Open your site, open your browser devtools, and look at the Network tab while loading a page. You should see POST requests to /v0/events on your tracking host (or to your own proxy path if you configured one) returning a 2xx status.

    warning

    Events are only sent after the visitor grants consent through Uniform Context, and are suppressed inside the Uniform contextual editor. If you see no requests, check both of these before looking anywhere else.

  3. Open the Insights dashboard for the project and confirm activity appears.

If the dashboard stays empty:

  • Confirm you are looking at the project the token was generated for.
  • Confirm the environment variables match what Settings > Insights shows.
  • Confirm you deployed the build that contains the plugin registration.
  • Remember that some widgets only appear once the relevant Context entities exist. Signals, audiences, intents, enrichments, tests, and personalizations each drive their own widget.

Sending events to your own API route instead of directly to Uniform's tracking domain keeps all analytics traffic on your own origin, which avoids ad blockers that filter requests by domain. It also keeps the tracking token on the server.

Point the plugin at a local path instead of a host:

createUniformContext.ts

import { Context, ContextPlugin } from '@uniformdev/context' import { createInsightsPlugin } from '@uniformdev/insights' export function createUniformContext() { const plugins: ContextPlugin[] = [] if (typeof window !== 'undefined' && window.document) { plugins.push( createInsightsPlugin({ endpoint: { type: 'proxy', path: '/api/analytics-proxy', projectId: process.env.NEXT_PUBLIC_UNIFORM_PROJECT_ID!, }, }) ) } return new Context({ manifest, plugins }) }

Then add the route that forwards to Uniform. Because the token now lives on the server, these variables no longer need the NEXT_PUBLIC_ prefix.

pages/api/analytics-proxy.ts

import { createBackendInsightsProxyHandler } from '@uniformdev/insights/proxy' import { NextApiRequest, NextApiResponse } from 'next' const proxyHandler = createBackendInsightsProxyHandler({ apiHost: process.env.UNIFORM_INSIGHTS_API_URL!, apiKey: process.env.UNIFORM_INSIGHTS_API_KEY!, }) export default async function handler(req: NextApiRequest, res: NextApiResponse) { const proxyResponse = await proxyHandler.handleRequest(String(req.body)) res.status(proxyResponse.status).json(await proxyResponse.json()) }

createInsightsPlugin accepts the following options. Only endpoint is required.

OptionDescription
endpointWhere events are sent. Either { type: 'api', host, apiKey, projectId } to post directly to Uniform, or { type: 'proxy', path, projectId } to post to your own route.
sessionDurationSecondsHow long a session stays open without activity. Defaults to 1800 (30 minutes). A visitor returning after this window starts a new session.
batchConfigEnables batching and deduplication of events. Omitted by default, which sends each event as its own request. Passing any object turns batching on; unset fields fall back to a maximum of 50 events per batch, a 2 second delay, a 1 MB payload, and 1 request per second.
storageA custom store for the visitor and session identifiers. Defaults to localStorage. createMemoryStorage is exported for environments without it.
getVisitorIdAn async function returning the anonymous visitor identifier. Override only to persist a device-generated anonymous ID; do not use email, account IDs, or other PII—the value is sent with every event.
getSessionIdAn async function returning the session identifier, called whenever a new session starts.

Summary

Insights is now collecting. Next, decide what counts as a conversion by configuring a goal, then read the results in the Insights dashboard.