> ## Documentation Index
> Fetch the complete documentation index at: https://canopy.wnstn.space/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Event and User Properties in Cano Analytics

> Add typed properties to events and user profiles to make your Cano data fully queryable, filterable, and useful in every chart and dashboard.

Properties let you attach rich context to every event and user record, turning raw event names into a fully queryable dataset. A `purchase_completed` event becomes far more useful when it carries the plan name, amount, currency, and billing cycle — all of which you can filter and group by in any Cano chart.

## Supported Property Types

Cano Analytics supports five property types. Use the correct type from the start — property types are inferred on first ingestion and affect how values are displayed and filtered in your dashboards.

| Type       | Example value            | Notes                          |
| ---------- | ------------------------ | ------------------------------ |
| `string`   | `"pro"`                  | Max 1,024 characters per value |
| `number`   | `49` or `3.14`           | Integer or float               |
| `boolean`  | `true` / `false`         |                                |
| `datetime` | `"2024-06-01T00:00:00Z"` | ISO 8601 format required       |
| `array`    | `["startup", "saas"]`    | Array of strings only          |

## Property Limits

* **200 unique property keys** per event type (e.g., `purchase_completed` can have up to 200 distinct keys)
* **1,024 characters** maximum per string value
* Values exceeding the character limit are truncated at ingestion — no error is thrown

Plan your property names before you ship. Renaming or removing property keys must be done manually in your Cano dashboard under **Settings → Properties**, and affects all historical data for that event type.

## Sending Mixed-Type Properties

The example below shows all five property types in a single event. Use it as a template when designing a new event schema.

<CodeGroup>
  ```javascript JavaScript theme={null}
  cano.track('subscription_started', {
    plan: 'pro',                           // string
    seats: 5,                              // number
    annual_billing: true,                  // boolean
    trial_ends_at: '2024-06-01T00:00:00Z', // datetime
    tags: ['startup', 'saas']             // array
  });
  ```

  ```python Python theme={null}
  client.track(
      user_id='usr_123',
      event='subscription_started',
      properties={
          'plan': 'pro',                            # string
          'seats': 5,                               # number
          'annual_billing': True,                   # boolean
          'trial_ends_at': '2024-06-01T00:00:00Z',  # datetime
          'tags': ['startup', 'saas']              # array
      }
  )
  ```
</CodeGroup>

## Reserved Properties

The following property keys are reserved and set automatically by Cano on every event. Do not include them in your `track()` or `identify()` calls — any values you provide will be overwritten.

| Reserved key   | Set by | Description                                         |
| -------------- | ------ | --------------------------------------------------- |
| `event_name`   | Cano   | The name string you passed to `track()`             |
| `user_id`      | Cano   | The user ID from `identify()` or the `track()` call |
| `anonymous_id` | Cano   | Auto-generated ID for unauthenticated sessions      |
| `timestamp`    | Cano   | Client-side time the event was created (ISO 8601)   |
| `received_at`  | Cano   | Server-side time the event arrived at the Cano API  |

If you need to capture similar information under a custom key, use a different name (e.g., `server_timestamp` instead of `timestamp`).

## Super Properties

Super properties are key-value pairs you register once that are automatically merged into **every subsequent `track()` call**. They're useful for global context like app version, environment, or experiment variant — values that apply to all events but would be tedious to repeat manually.

```javascript JavaScript theme={null}
// Set super properties once — typically on app init
cano.setSuperProperties({
  app_version: '2.1.0',
  environment: 'production',
  experiment_variant: 'checkout_v2'
});

// All subsequent track() calls include the super properties automatically
cano.track('page_viewed', { page: '/dashboard' });
// Sent as: { page: '/dashboard', app_version: '2.1.0', environment: 'production', experiment_variant: 'checkout_v2' }

cano.track('button_clicked', { button: 'upgrade_cta' });
// Sent as: { button: 'upgrade_cta', app_version: '2.1.0', environment: 'production', experiment_variant: 'checkout_v2' }
```

To remove a super property, call `cano.unsetSuperProperty('key')`. To clear all super properties, call `cano.clearSuperProperties()`.

<Info>
  Super properties are stored in memory and reset when the page reloads. For persistent super properties across sessions, store the values in `localStorage` and re-register them on each page load.
</Info>

## Using Properties in Dashboards

Once your events are flowing, you can use any property in the Cano dashboard to slice and analyze your data.

<Tabs>
  <Tab title="Filter by Property">
    In any chart or funnel, open the **Filters** panel and select a property key and value. For example, filter `purchase_completed` events where `plan = pro` to see only Pro plan conversions.
  </Tab>

  <Tab title="Group By Property">
    Use **Group By** in chart queries to break down a metric by a property dimension. For example, group `subscription_started` by `plan` to compare Free vs. Pro vs. Enterprise signups over time.
  </Tab>

  <Tab title="Segment Users">
    In the **Users** section, filter your user list by any trait you've sent via `identify()`. For example, find all users where `plan = pro` and `annual_billing = true` to target your highest-value cohort.
  </Tab>
</Tabs>

<Warning>
  **Avoid sending PII as event properties.** Do not include email addresses, full names, phone numbers, social security numbers, or other personally identifiable information in your `track()` calls. PII belongs in user traits sent via `identify()`, where it is governed by your data retention and deletion policies. Sending PII as event properties makes it significantly harder to comply with GDPR deletion requests, since event records are immutable.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Event Tracking" icon="bolt" href="/docs/tracking/event-tracking">
    Review event naming conventions, batch sending, and how to view your real-time event stream.
  </Card>

  <Card title="Identify Users" icon="user" href="/docs/tracking/identify-users">
    Learn how to attach traits to user profiles and link anonymous sessions to known users.
  </Card>
</CardGroup>
