# First-party proxy

Your server serves the script and forwards events on paths of your own site, such as `/js/script.js` and `/api/event`. To a browser and to a blocker, these are requests to your site like any other. This is the strongest setup against [ad blockers](./blockers.md).

The proxy sends events with a secret key and the visitor's real address and browser, 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`.
3. Send the two paths to `proxy()`:

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

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

export default {
  async fetch(request, env, ctx) {
    let url = new URL(request.url);
    if (url.pathname === "/js/script.js" || url.pathname === "/api/event")
      return analytics.proxy(request);
    return app.fetch(request, env, ctx);
  },
};
```

4. Load the script from your path, and send events to your path:

```html
<script
  defer
  src="/js/script.js"
  data-site="YOUR_SITE_ID"
  data-endpoint="/api/event"
>
</script>
```

With the [npm package](./npm.md), you need only the event path:

```js
let analytics = crowne("YOUR_SITE_ID", { endpoint: "/api/event" });
```

## What the proxy does

- `GET` of a path that ends in `.js` answers with the script, cached for one hour.
- `POST` forwards a batch of up to 50 events to crowne, with the visitor's address, browser, and location from your CDN.
- Other methods answer `405`.

Pick paths that do not say "analytics" or "tracking". Some blockers block paths by name, such as `/analytics.js`.
