# What tode tracks and why

tode records three kinds of events from a plugin: an **action**, an **action with a number**, and a **session**. Each event carries a few fields about where it happened. This page lists every field, the number on the dashboard it feeds, and what that number tells you about your plugin.

Nothing here is read from the document. tode never sees file names, layer names, text, selections or images. It sees the events you send and the environment they came from.

## The three events

### Action

```typescript
tode.trackAction('replace_fonts');
```

One name, one moment. You call it where something happens: a button, an export, a feature that finished its work.

**On the dashboard:** *Actions per day* stacked by name, *Actions by name* with each name's share, and *Feature adoption*, the share of active users who did a given action at least once in the range.

**Why it is useful:** the names are your feature list. Over a month they show which features earn their place and which nobody opens, so you know what to improve, what to promote and what to drop. When a new release changes the share of one action against the others, the *Changed* line on the dashboard points at it.

### Action with a number

```typescript
tode.trackActionWithMetric('fonts_replaced', 42);
```

The same, with a value: how many layers were processed, how many fonts were replaced, how long a job took.

**On the dashboard:** *Metric totals per day* and *Metric values* with count, average, median (p50), p95 and maximum per metric name.

**Why it is useful:** a count says the feature ran; the number says how hard it worked. A p95 of 1,200 layers tells you the plugin meets big files, and whether to optimise for them. The totals say how much work the plugin did for its users in a month, which is a number worth putting on a pricing page.

### Session

Sessions are not a call. When the plugin UI opens, the SDK opens a WebSocket to tode; when the plugin closes, the socket closes and the server records how long it was open. The SDK never sends a session payload itself.

**On the dashboard:** *Sessions per day* with the average length, *Session length* as a histogram (under 10 s, 10–30 s, 30 s–1 min, 1–2 min, 2–5 min, 5–10 min, 10–30 min, over 30 min) with p50 and p95, and the *Avg session* tile.

**Why it is useful:** length is the honest measure of whether the plugin does a job. Sessions under ten seconds are people who opened it and left; a healthy utility plugin sits around one to five minutes. The histogram also shows the two kinds of users a plugin often has: the quick-task crowd and the ones who live in it.

## The fields on every event

Every event, whichever kind, carries these. The SDK fills them in; you never set them by hand.

### `actionName`

The name you passed. Keep names stable across releases, in `snake_case`, and fewer than your plan's event-type limit (see [Plans and Limits](https://docs.usetode.dev/plans)). The dashboard groups and counts by the exact string.

### `actionValue`

Only on an action with a number. Any finite number up to 10<sup>12</sup>; counts and durations never get near that.

### `timestamp`

When the event happened, in milliseconds, from the user's clock. If that clock is more than ten minutes off the server's, the server time is used instead, so history cannot be backfilled by accident.

**Feeds:** every per-day chart, the *Activity by hour* heatmap (weekday × hour, shown in your local time), the *Busiest on* note, and the detection of an unusual day against its seven-day baseline.

### `figma_userId`

The user's Figma id, as a string, read from `figma.currentUser`. It is only available when the plugin manifest asks for it:

```json title="manifest.json"
{
  "permissions": ["currentuser"]
}
```

Without the permission the SDK sends an empty value and tode cannot tell one user from another.

**Feeds:** *Unique users*, *Active users* per day split into new and returning, *Returning users* (a user is new when their first ever event for this plugin falls inside the range), *Stickiness* (DAU / MAU over the last 28 days), *Week-one retention* (users first seen in a week, and how many of them had any event the week after), *Feature adoption*, and the milestones in the *Growing* line (passed 1,000 users, and so on).

**Why it is useful:** this is the field that separates a usage counter from analytics. Actions tell you how often a feature runs; users tell you how many people it runs for and whether they come back. Retention is the one number that predicts whether a paid plan will hold.

tode keeps the id and nothing else about the person: no name, no email, no avatar. The dashboard only ever shows users in aggregate.

### `figma_editorType`

Where the plugin ran: `figma` (Figma Design), `figjam`, `dev` (Dev Mode), `slides` or `buzz`. Anything else is dropped rather than stored as a category of its own.

**Feeds:** the *Environment* widget, and the *Changed* line when one editor's share moves against the previous period.

**Why it is useful:** a plugin built for Figma Design that gets a third of its sessions from Dev Mode has a second audience it did not plan for. The split also tells you which editor to test a release in first.

### `figma_mode`

The editor's mode at the time: `default`, `inspect`, `codegen`, `textreview`, `linkpreview`, `auth`, `query` or `textrun`.

**Feeds:** the mode breakdown in the Environment widget and the same share-shift detection.

**Why it is useful:** in Dev Mode the difference between `inspect` and `codegen` is the difference between someone reading a design and someone generating code from it. For a codegen plugin that is the whole product.

### `eventSource`

Where in the plugin the event came from: `ui` (the plugin's iframe), `plugin` (the controller, `code.ts`) or `widget`.

**Feeds:** the *Event source* share in the Environment widget.

**Why it is useful:** it tells you whether people use the plugin through its interface or through things that run without one, such as a widget or a command from the controller. That changes where to spend design effort.

### `userCountry`

A two-letter country code. When the plugin starts, the SDK asks tode for the country of the current connection; the server answers from the request's IP and the SDK sends the code with every event. The IP address itself is not stored.

**Feeds:** *Visitors by country* and the world map, and the *Changed* line when a country's share shifts.

**Why it is useful:** language, pricing and support hours. A plugin with a growing share of users in Brazil or Japan has a localisation decision to make, and the map makes that visible before the support emails do.

### `figma_pluginId` and `figma_widgetId`

The plugin's id from the manifest, and the widget's id when the code runs as a widget. tode checks the event belongs to the plugin the API key was issued for; the ids are not shown on the dashboard.

### `figma_apiVersion`, `appSource`

The Figma plugin API version the plugin runs on, and the host application (`figma` today). Kept for support and debugging; neither appears on the dashboard.

## What the dashboard adds on top

From the events above, tode computes a few readouts that are not stored anywhere, only derived:

- **Growing / Steady / Slipping / Quiet.** Users in the range against the previous period, with actions alongside. *Quiet* means fewer than 50 events, too few to judge.
- **Changed.** The single strongest shift in the range: a day far above or below its seven-day baseline, or a category (editor, mode, country or action) whose share moved by 1.5× or more.

All of them are aggregates. There is no per-user view, by design.

## What is never collected

- The document: file names, page names, layers, text, selections, images, comments.
- The person: name, email, avatar, team. Only the Figma user id, and only with the `currentuser` permission.
- The network: the IP address is used once to resolve the country and is not stored.
- Cookies: none. The SDK sets nothing in the browser.

The full list of fields is the SDK's `types.ts`, which is [open source](https://github.com/kolebayev/tode-sdk).

## Next steps

- [Best Practices](https://docs.usetode.dev/best-practices): naming actions so the dashboard stays readable
- [Plans and Limits](https://docs.usetode.dev/plans): how events and event types count against a plan
- [tode.trackAction()](https://docs.usetode.dev/api/track-action) and [tode.trackActionWithMetric()](https://docs.usetode.dev/api/track-action-with-metric)

Source: https://docs.usetode.dev/what-tode-tracks
