# Props & privacy

> Add context to events without collecting personal data.

Source: https://shipabase.dev/docs/props

`example`

```ts
trackEvent("invoice_sent", { plan: "pro", count: 3, success: true });
```

| Limit | Value |
| --- | --- |
| Keys per event | 20 |
| Key length | 40 characters |
| Values | string (≤ 200 characters), finite number or boolean |
| Nesting | Not allowed: no objects or arrays |

Invalid props are dropped. In debug mode, the console shows a warning.

## Keep props anonymous

You decide what you send, and you are responsible for it. Shipabase is built for anonymous analytics: the server already derives an anonymous daily visitor hash and a country, so props only need to describe the action (`plan`, `count`, `variant`), not the person.

Personal data in props (emails, names, user or account IDs, phone numbers, IP addresses, tokens, free text typed by users) would link events back to a person, defeat the daily visitor hash, and bring GDPR obligations back to your app.

## Built-in guard

As a safety net, the API masks values that look personal before anything is stored. The event and the key are kept, the value becomes `[redacted]`, so you can spot it in the dashboard and fix the call.

| Masked | Examples |
| --- | --- |
| Keys that name personal data | `email`, `phone`, `user_id`, `username`, `first_name`, `ip`, `token`, `password`, `address`… |
| Emails anywhere in a value | `alice@example.com` |
| Phone numbers, IP addresses, JWTs | `+33 6 12 34 56 78`, `203.0.113.42`, `eyJ…` |

> The guard catches common mistakes, it is not a guarantee. Numbers and booleans are never masked, and free text can still contain a name: keep props to values you choose.
