# Setup

> Set up your Analytics Server.

Choose hosted analytics or run your own server, then connect your player.

## Before you begin

You need a Chunkify Project, owner access to its settings, and an application with a playable video and the [playback tracker](/docs/integration/analytics#install-the-tracker).

Your production website must use the server's public HTTPS address. Keep private analytics keys on your backend; the tracker uses only a public player key.

## Use analytics hosted by Chunkify

<steps>
    <step title="Add an Analytics Server">
        Open your Project's **Analytics > Settings**, select **Add server**, and choose **Hosted by Chunkify**. Give it a name and create it.
    </step>
    <step title="Allow your website">
        Open the server's configuration and add your application's origin under **Allowed origins**. Include its scheme and port when present, such as `https://app.example.com` or `http://localhost:3000`.
    </step>
    <step title="Copy the player settings">
        Copy the server URL and the public **Player** key from its settings. Use them in the tracker example below.
    </step>
    <step title="Send events and open Analytics">
        Play a video in your application, then open **Analytics** in Chunkify and select that server. Use a date range that includes the playback attempt.
    </step>
</steps>

### Connect your player

Replace the URL and public key with the settings from your server, and the sample Asset ID with your video's ID. The endpoint includes `/v1/events`. This example uses an existing native `<video>` element:

```javascript
import { monitor } from '@chunkify/player-analytics';
import { createChunkifyAdapter } from '@chunkify/player-analytics/chunkify';

const video = document.querySelector('video');
if (!video) throw new Error('Missing video element');

const session = monitor(video, {
    videoId: 'ast_3Ljtoej7c3Y1plabZoElbQwdwLh',
    destinations: [
        createChunkifyAdapter('https://analytics.chunkify.dev/v1/events', {
            ingestKey: 'YOUR_PUBLIC_PLAYER_KEY',
        }),
    ],
});
```

Use the appropriate [player connector](/docs/integration/analytics#connect-your-player) for Chunkify Player, hls.js, Video.js 10, or Shaka. Keep `session` and call `session.destroy()` when removing the player or disabling tracking.

Use any stable ID to identify your video. If you use the ID of an Asset in the same Chunkify Project, the Chunkify dashboard also links to that Asset and displays its title, poster, and timeline thumbnails when available.

Replace any existing tracking session rather than attaching a second one to the same player.

The tracker sends snapshots during playback and a final event when the attempt ends. Watch time may still be zero immediately after playback starts. See [Send events](/docs/integration/analytics/send-events) for context and delivery options.

**Default for dashboard players** selects the server used by Chunkify previews, the playground, and newly generated player snippets. Existing players on your website keep their own configuration.

## Run a self-hosted server

You need Docker with Compose. The stack runs ClickHouse, the Analytics Server, and a gateway that spreads requests across your servers, using the `0.18.0` release. For native installation, see the [server installation guide](https://github.com/chunkifydev/chunkify-analytics/tree/v0.18.0#install-without-docker).

### Download the stack

```sh
mkdir -p chunkify-analytics
cd chunkify-analytics
base=https://raw.githubusercontent.com/chunkifydev/chunkify-analytics/v0.18.0/examples/clickhouse
for file in compose.yaml Caddyfile clickhouse.xml config.toml .env.example; do
  curl --fail --location "$base/$file" --output "$file"
done
cp .env.example .env
echo 'CHUNKIFY_IMAGE=ghcr.io/chunkifydev/chunkify-analytics:0.18.0' >> .env
```

Set `CLICKHOUSE_PASSWORD` in `.env` to a long random value.

Edit the existing `[server]` section in `config.toml`. Allow your website and `https://chunkify.dev` if you will use Chunkify previews or the playground:

```toml
[server]
allowed_origins = ["http://localhost:3000", "https://chunkify.dev"]

[retention]
seconds = 2592000
```

Use your production application's exact origin when deploying. Retention in this example is 30 days. Keep the rest of the downloaded configuration.

### Initialize once

```sh
docker compose run --rm analytics init
```

`init` creates the database and returns the initial `public_key` and full-access `secret_key` once. Save them privately. ClickHouse stores only their hashes, so the keys cannot be recovered later.

Run `init` only for a new installation. It refuses to initialize the same database twice.

### Start the server

```sh
docker compose up -d
```

Check health:

```sh
curl --fail http://127.0.0.1:4174/healthz
docker compose logs analytics
```

A healthy server returns `{"status":"ok"}`. The image includes its geolocation database; no local build is needed.

The `clickhouse-data` volume holds all events, analytics projects, and key hashes. Keep it when replacing containers. Analytics servers keep no data, so you can run more of them to handle more traffic:

```sh
docker compose up -d --scale analytics=3
```

The gateway accepts requests on your computer only. Before connecting from Chunkify or a deployed website, expose it through an HTTPS reverse proxy at a public address you control.

Set `server.public_url` to that external base URL so exported download links use an address reachable by your users.

Forward `/v1/` requests and ingestion `OPTIONS` requests. If you expose MCP, forward `/mcp` and add your public hostname to `[mcp].allowed_hosts`. See [Configuration](/docs/integration/analytics/server/configuration#browser-access).

### Connect it to Chunkify

Create a read-only project key from the stack directory:

```sh
docker compose exec analytics \
  chunkify-analytics key create default secret "Chunkify dashboard" --read-only
```

Save the returned `key`. In your Project's **Analytics > Settings**, add a **Self-hosted** server with its public base URL and this read-only key. The base URL excludes `/v1/events` and `/mcp`.

Add the project's public key if you want Chunkify previews and generated player examples to send events. This is the `public_key` returned at initialization for the `default` analytics project.

Connect your application using the [tracker example above](#connect-your-player), with your own server's `/v1/events` URL and public key. The analytics project selected by the public key must match the one selected by the dashboard's read-only key.

The Chunkify dashboard must be able to reach your server over public HTTPS. A loopback URL is useful for testing the tracker locally, but is not reachable from the hosted Chunkify app.

## Check your first playback

Open [Sessions](/docs/integration/analytics/server/dashboard#sessions) for the selected server. You should see a playback attempt after playing the video. Watch time updates as snapshots or a final event arrive.

For missing events, inspect the browser request to `/v1/events`. Check the public key, full endpoint URL, allowed website origin, and selected dashboard server. [Ingestion responses](/docs/integration/analytics/server/configuration#ingestion-responses) explains common errors.

You can also check recent events from your terminal. Save a read-only key as `ANALYTICS_SECRET_KEY` in your private environment, then query your server's URL:

```sh
curl --fail \
  -H "Authorization: Bearer $ANALYTICS_SECRET_KEY" \
  'https://analytics.example.com/v1/events?order=desc&limit=10'
```

The response contains an `events` array with the original events, their server receipt times, and their analytics project ID.
