# First-run events

The hook reports one of three event types. Two of them are conversions, counted once per installation.

| Event | Report it | Counted |
| --- | --- | --- |
| `install_completed` | After every installation step succeeded. | Once per installation ID. The default. |
| `first_run` | From your CLI's entry point, on launch. | Once per installation ID. |
| `install_started` | Before installing, to measure attempts. | Once per installation ID. Not a conversion: only webhooks receive it. |

## Installation IDs

On its first run, the hook creates a random 128-bit installation ID and keeps it in `<state dir>/<service>/<website>/<scope>.id`, where the state dir defaults to `~/.local/state/clitrail`. Later reports from the same user, website and scope reuse it, so launching your CLI a hundred times still produces one `first_run`. Updating the hook you bundle keeps existing IDs: in the default folder, a hook with no ID yet reuses the one an older copy kept under `~/.local/state/opfs-attribution-shell`.

- A repeated report of the same event type for the same installation, `install_started` included, returns the original result with `"duplicate": true`. A pre-install hook that runs several times counts one attempt.
- Reusing an `event_id` with the same installation and type is idempotent. Reusing it for anything else is refused with `event_id_conflict`.
- Destinations receive one conversion per installation and event type, identified by a stable event ID the platforms deduplicate on.

## Installation scopes

Use `--installation-scope` (or `CLITRAIL_INSTALLATION_SCOPE`) when one website ships several products, or one product can be installed several independent times on a machine. Each scope gets its own installation ID.

## Choosing the event

- Use `install_completed` where your code runs at the end of a real install: a shell installer or an npm `postinstall`.
- Use `first_run` where there is no install step you control: npx, Homebrew launchers, Python entry points and single binaries. It counts people who actually launch the CLI, not downloads.

Google Ads, Meta, TikTok and X Ads destinations send `install_completed` only until you tick `first_run` in their events; GA4 and webhooks send both by default. X Ads sends first runs to a second event of your pixel, so they never count as installs.

## Late receipts

An install is resolved when it is first reported. If it was unmatched, reporting it again does not attach a receipt that became readable later.
