# Activate Uniform Insights

> Generate a tracking token for your project and register the Insights plugin in your front end so Uniform starts collecting analytics data.

Source: https://docs.uniform.app/docs/guides/insights/activate-insights

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

- A Uniform project with Insights enabled. Contact [support](mailto:support@uniform.dev) 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](https://docs.uniform.app/docs/guides/classification).

## Generate a tracking token

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.

## Install the package

```bash
npm i @uniformdev/insights
```

## Register the plugin

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`

```typescript
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`.

## Add the environment variables

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

**Next.js**

```bash
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>
```

**Other frameworks**

```bash
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 US region:_

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

_For the EU region:_

For the Europe region the host is `https://analytics.eu.uniform.global`.

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

## Improve event attribution

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.

**Next.js Page Router**

Pass `matchedRoute` and `dynamicInputs` into `<UniformComposition>`.

`[[...path]].tsx`

```typescript
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}
    />
  )
}
```

**Next.js App Router (v2 SDK)**

Pass the route resolution `result` into `<UniformContext>`.

`page.tsx`

```typescript
// ./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](mailto:support@uniform.dev) if you need help wiring up composition attribution.

## Verify tracking is working

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](https://docs.uniform.app/docs/guides/insights/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.

## Route events through your own proxy

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`

```typescript
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`

```typescript
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())
}
```

## Plugin options

`createInsightsPlugin` accepts the following options. Only `endpoint` is required.

| Option | Description |
| --- | --- |
| `endpoint` | Where 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. |
| `sessionDurationSeconds` | How long a session stays open without activity. Defaults to `1800` (30 minutes). A visitor returning after this window starts a new session. |
| `batchConfig` | Enables 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. |
| `storage` | A custom store for the visitor and session identifiers. Defaults to `localStorage`. `createMemoryStorage` is exported for environments without it. |
| `getVisitorId` | An 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. |
| `getSessionId` | An async function returning the session identifier, called whenever a new session starts. |

Insights is now collecting. Next, decide what counts as a conversion by [configuring a goal](https://docs.uniform.app/docs/guides/insights/measure-conversions), then read the results in the [Insights dashboard](https://docs.uniform.app/docs/guides/insights/insights-dashboard).
