# Programmatic classification

> This section provides information on how to programmatically control the classification process.

Source: https://docs.uniform.app/docs/guides/classification/programmatic-classification

The Uniform tracker is responsible for classifying the visitor
based on their behavior.

## The Uniform tracker

You need to add the tracker to your front-end application and be able to get a reference to it when you need to use it.

### Add the tracker

The [Context](https://sdk.uniform.app/context.context)
type represents the Uniform tracker. The tracker must be added
to the front-end application before any classification can happen.

**Next.js**

1. Add the following packages to your app:

   ```
   @uniformdev/context
   @uniformdev/context-react
   ```
2. Add the following code to the `_app.js` file:

   ```jsx
   import { UniformContext } from '@uniformdev/context-react';
   import { Context } from '@uniformdev/context';

   const context = new Context({
     consent: true,
     manifest: {
       project: {},
     },
   });

   function MyApp({ Component, pageProps }) {
     return (
       <UniformContext context={context}>
         <Component  {...pageProps} />
       </UniformContext>
     );
   }
   ```

   > **Info:**
   >
   > This example includes a hard-coded manifest. Your code
   > should use the manifest for your Uniform project. For
   > information on how to retrieve the manifest, see the
   > [manifest guide](https://docs.uniform.app/docs/guides/classification/manifest).

### Get reference to the tracker

Before you can use the tracker, you must get a reference to it.

**Next.js**

To get a reference to the tracker from inside a React component, the hook `useUniformContext` is used.

```jsx
import { useEffect } from 'react';
import { useUniformContext } from '@uniformdev/context-react';

export function MyComponent() {
  const { context } = useUniformContext();

  useEffect(() => {
    //
    //Do something with the tracker when the component is loaded.
  }, []);
  
  return <div>My component here!</div>
}
```

## Write tracker data

The Uniform SDK provides the ability for you to add logic to
your application that explicitly captures visitor activity
for the purpose of classifying the visitor.

### Enrichments

If you are using Uniform Canvas, any [enrichments](./enrichments)
that are assigned to a component are tracked automatically.
However, if you aren't using Canvas, you must track
enrichments in your application.

You can use the Uniform tracker to track enrichments. The
following example demonstrates how to add a button that
can track enrichments.

**Next.js**

```jsx
import { useUniformContext } from '@uniformdev/context-react';
export function EnrichmentTriggerButton() {
  const { context } = useUniformContext();
  const onClick = async (e) => {
    e.preventDefault();
    await context.update({
      enrichments: [{ 
        str: 10, 
        cat: 'colorPreference', 
        key: 'red',
      }],
    });
    alert('Enrichment was set.');
  }
  return <button onClick={onClick}>Track enrichments</button>
}
```

> **Tip:**
>
> This code requires the manifest has an enrichment category
> `colorPreference` with an enrichment value `red`.

You can also use front-end specific components to track enrichments.

**Next.js**

You can use a React hook to track enrichments.

```jsx
import { Track } from '@uniformdev/context-react';
export function TrackEnrichment() {
  const behavior = [
    { 
      str: 10, 
      cat: 'colorPreference', 
      key: 'red',
    }
  ];
  return <Track behavior={behavior} />
}
```

> **Info:**
>
> This code requires the manifest has an enrichment category
> `colorPreference` with an enrichment value `red`.

### Events

An event can trigger a signal. You can use the Uniform tracker
to write events. The following example demonstrates how to add
a button that can write events.

**Next.js**

```jsx
import { useUniformContext } from '@uniformdev/context-react';
export function EventsTriggerButton() {
  const { context } = useUniformContext();
  const onClick = async (e) => {
    e.preventDefault();
    await context.update({
      events: [
        { event: "event1" }, 
        { event: "event2" },
      ],
    });
    alert('2 events were sent.');
  }
  return <button onClick={onClick}>Send events</button>
}
```

### Quirks

A quirk can trigger a signal. You can use the Uniform tracker to write quirk values.

#### Client-side

The following example demonstrates how to add a button that can write quirks.

**Next.js**

```jsx
import { useUniformContext } from '@uniformdev/context-react';
export function QuirksTriggerButton() {
  const { context } = useUniformContext();
  const onClick = async (e) => {
    e.preventDefault();
    await context.update({
      quirks: {
        city: "San Francisco",
        persona: "Shopper",
      },
    });
    alert('2 quirks were set.');
  }
  return <button onClick={onClick}>Set quirks</button>
}
```

#### Server-side

You can set quirks in code that runs during server-side rendering.

**Next.js (page router)**

1. Add the following file to the root of your application:

   `createUniformContext.js`

   ```jsx
   import { Context, enableContextDevTools } from "@uniformdev/context";
   import { NextCookieTransitionDataStore } from "@uniformdev/context-next";

   import manifest from "./contextManifest.json";

   export function createUniformContext(serverContext) {
     return new Context({
       defaultConsent: true,
       manifest,
       transitionStore: new NextCookieTransitionDataStore({
         serverContext,
       }),
       plugins: [enableContextDevTools()],
     });
   }
   ```
2. Add the following to your `_document.js` or `_document.tsx` file:

   ```jsx
   import Document, { Html, Head, Main, NextScript } from "next/document";
   import { enableNextSsr } from "@uniformdev/context-next";
   import { createUniformContext } from "../createUniformContext";

   class MyDocument extends Document {
     static async getInitialProps(ctx) {
       const context = createUniformContext(ctx);
       await context.update({
         quirks: {
           location: "YOUR LOCATION",
         },
       });
       enableNextSsr(ctx, context);
       return await Document.getInitialProps(ctx);
     }
     render() {
       return (
         <Html lang="en">
           <Head />
           <body>
             <Main />
             <NextScript />
           </body>
         </Html>
       );
     }
   }
   export default MyDocument;
   ```

   > **Note:**
   >
   > This code demonstrates how to set the value of a quirk named `location`.
3. Add the following to your `_app.js` or `_app.tsx` file:

   ```jsx
   import { UniformContext } from "@uniformdev/context-react";
   import { createUniformContext } from "../createUniformContext";

   export default function App(props) {
     const { Component, pageProps, serverUniformContext } = props;
     const context = createUniformContext(serverUniformContext);
     return (
       <UniformContext context={serverUniformContext ?? context}>
         <Component {...pageProps} />
       </UniformContext>
     );
   }
   ```

## Read tracker data

The Uniform tracker enables you to read the classification data
for the current visitor.

### Quirks

You can read the [quirks](https://docs.uniform.app/docs/guides/classification/quirks)
that are currently set on the visitor.

**Next.js**

You can use a React hook to read the quirks currently set on
the visitor. This example creates a component that displays
the visitor's current quirks.

```jsx
import { useQuirks } from '@uniformdev/context-react';
export function ShowQuirks() {
  const quirks = useQuirks();
  return <div>{JSON.stringify(quirks)}</div>
}
```

### Scores

You can read the [visitor dimension](./visitor-dimensions) ([audiences](./audiences),
[enrichments](./enrichments), [intents](./intents), and [signals](./signals)) scores that
are current set on the visitor.

**Next.js**

You can use a React hook to read the scores currently set on
the visitor. This example creates a component that displays
the visitor's current scores.

```jsx
import { useScores } from '@uniformdev/context-react';
export function ShowScores() {
  const scores = useScores();
  return <div>{JSON.stringify(scores)}</div>
}
```

## Handle tracker events

You can define event handlers for the events that are emitted from the Uniform tracker during the classification process.

### Quirks updated

### Scores updated

## Set score decay

The Uniform tracker automatically reduces visitor dimension
scores over time through a process called decay. See the
[score decay guide](./score-decay)
for information on how to control score decay.

## Clear tracker data

This example demonstrates how to implement a "forget me" button.

**Next.js**

```jsx
import { useUniformContext } from '@uniformdev/context-react';
export function ForgetMeButton() {
  const { context } = useUniformContext();
  const onClick = async (e) => {
    e.preventDefault();
    await context.forget(true);
    alert('All tracker data was cleared.');
  }
  return <button onClick={onClick}>Forget me</button>
}
```
