# Server events

Send events from your server when you cannot run a script, or when the event happens on the server, such as a payment. The client forwards the visitor's address, browser, and location from your CDN, so visitors count the same as with the script.

## Set it up

1. In the app, open the org's **Keys** page and make a key with the `ingest` scope.
2. Store it as a secret, such as `CROWNE_KEY`. Do not send it to the browser.
3. Start the client once, and send events in `waitUntil` so the response does not wait for them:

```js
import { crowne } from "crowne/server";

let analytics = crowne({ key: env.CROWNE_KEY, site: "YOUR_SITE_ID" });

export default {
  async fetch(request, env, ctx) {
    ctx.waitUntil(analytics.pageview(request));
    return new Response("Hello");
  },
};
```

## Custom events

Give `track()` the visitor's request, so the event counts for the right visitor.

```js
ctx.waitUntil(
  analytics.track(request, "purchase", { plan: "pro", amount: 49 }),
);
```

## Options

| Option     | Use                                                             |
| ---------- | --------------------------------------------------------------- |
| `key`      | A secret key with the `ingest` scope, `crw_live_…`. Required.   |
| `site`     | The site id the events count for. Required.                     |
| `endpoint` | Where events go. Default: `https://in.crowne.io/v1/events`.     |
| `fetch`    | The `fetch` function to send with. Default: the global `fetch`. |

Each call returns a promise. It rejects with the status and the error when crowne refuses the event, such as for a bad key.

The same client serves the [first-party proxy](./proxy.md) with `proxy(request)`.
