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

# What to capture

> Choose the customer profiles, events, and traits to send to Glyph.

Glyph places events on individual customer timelines alongside survey responses and notes. It does not use them to build funnels or aggregate product analytics.

Send events that help someone understand a specific customer's experience. If an event is only useful in aggregate, leave it in your analytics platform.

## Profile every known customer

Send a `profile` when a customer signs up or logs in, and whenever a trait changes. Profiles are upserts. Sent keys overwrite their stored values; omitted keys are preserved. A plan change can send `{ email, plan: "growth" }` without repeating the customer's name and company. To clear a trait, send a replacement value rather than omitting the key.

```ts theme={"dark"}
await glyph.profile("user_123", {
  email: "sarah@example.com",
  name: "Sarah Chen",
  plan: "pro",
  company: "Acme Inc",
  signedUpAt: "2026-05-12",
});
```

`userId` is the durable customer identity key. Every profile must include `email`, which Glyph uses to display and contact the customer.

Useful traits usually include name, plan, company, and signup date. Skip fields that won't affect how you interpret or respond to customer feedback.

### Known customers only

Every message requires a stable, non-empty `userId` from your system. Use a database ID rather than an email address, since email addresses can change. Glyph does not support anonymous identities or ID aliasing. Make sure your privacy notice and consent choices cover the customer data sent to Glyph.

Tracking an event for a new `userId` creates the customer record automatically. A later `profile` fills in the traits. Send the profile early so the timeline has a name and email from the start.

## Track the moments that carry meaning

Most products can start with four event categories:

| Category       | What it tells you                 | Examples                                                           |
| -------------- | --------------------------------- | ------------------------------------------------------------------ |
| **Activation** | The customer reached first value  | `Project created`, `First report exported`                         |
| **Core value** | They're getting what they pay for | `Invoice paid`, `Report exported`, `Campaign sent`                 |
| **Friction**   | Something got in their way        | `Export failed`, `Payment failed`, `Downgraded plan`               |
| **Lifecycle**  | Their relationship changed        | `Trial started`, `Subscription upgraded`, `Subscription cancelled` |

Include friction and lifecycle events, not only successful actions. For example, repeated `Export failed` events provide useful context for a survey response about unreliable exports.

<Tip>
  Capture business-critical events (payments, cancellations) server-side, where delivery doesn't depend on a browser session. Use the browser SDK for in-product actions and page views.
</Tip>

### Name events for reading, not querying

Event names appear verbatim on timelines. Use a past-tense phrase in sentence case, such as `Invoice paid` or `Export failed`. Avoid `snake_case` and screen-namespaced identifiers such as `dashboard.button.click`.

Keep the taxonomy stable: pick names once and reuse them exactly. `Invoice paid` and `Paid invoice` become two different signals.

### Properties add context, not identity

Properties are free-form JSON that add event-specific context such as amounts, plan names, and error codes:

```ts theme={"dark"}
await glyph.track("user_123", "Export failed", {
  format: "csv",
  reason: "timeout",
});
```

Put customer attributes in profile traits, not event properties. Properties describe the moment; traits describe the person.

## Record account context

If customers belong to teams or companies, record that context with `group`:

```ts theme={"dark"}
await glyph.group("user_123", "acme_inc", { plan: "enterprise" });
```

Today this appears as a group/account event on the customer's timeline. It does not create a separate account record or group-level analytics.

## Capture page views where they happen

The [browser SDK](/docs/sdks/browser) exposes `page` for recording page views. A page view can add context to another event; for example, a `Billing` view before `Payment failed`. Instrument product areas that are useful on a customer timeline rather than every route.

## Backfill with real timestamps

Every method accepts a `timestamp` option for historical data:

```ts theme={"dark"}
await glyph.track("user_123", "Invoice paid", { amount: 4900 }, {
  timestamp: new Date("2025-11-03T14:00:00Z"),
});
```

Omit `timestamp` for live events; the SDK sets it automatically. For larger imports, follow the [backfill guide](/docs/guides/backfill) for pacing, dry runs, and re-runnable scripts.

## What not to send

Glyph only receives data you send explicitly. Leave out:

* **Secrets and credentials** — passwords, API keys, session tokens.
* **Payment details** — full card numbers or bank details. Amounts and invoice IDs are fine.
* **Sensitive personal data** — health, government IDs, or anything your privacy policy doesn't cover sending to a processor.

For questions about retention, model processing, or security, contact [hello@glyph.app](mailto:hello@glyph.app) before sending the data.

## A working baseline

For a typical SaaS product, start with:

1. `profile` on signup, login, and plan change — with email, name, plan.
2. Three to five **core value** events, tracked server-side where possible.
3. Every **friction** event you can detect: failures, errors hit, downgrades.
4. **Lifecycle** events: trial started, subscribed, upgraded, cancelled.
5. `page` views for the main product areas, from the browser.

Review several customer timelines after a week, then add or remove events based on what is useful.
