Properties
Declare the properties a profile can store.
Settings → Profiles holds the properties a profile can store — the complete list of fields, their types, and which ones hold personal data.
Only declared properties are kept. Anything else that arrives from a source is dropped rather than stored, so the shape of a profile stays something you chose.
Only workspace admins can change the properties. Other members can view them.
Add a property
- Go to Settings → Profiles and find the Properties section.
- Click Add property.
- Enter a label — what people read in the admin.
- Enter a key — what syncs and rules refer to. Keys start with a letter and use only lowercase letters, numbers, and underscores.
- Pick a type and a role (both explained below).
- Tick Contains personal data if the value is personal.
- Click Save properties.
The whole set saves at once, so you can add, edit, and remove several properties and apply them in a single step. A row you started and left completely blank is discarded rather than blocking the save.
Built-in fields
The first rows of the list are locked. Every profile has them whether or not anything else is declared:
| Field | Key | What it holds |
|---|---|---|
| Display name | display_name | What lists and notifications show. |
email | The nudge target, and the default match key for additional sources. | |
| Domain | domain | The company match key. |
| Signed up | source_created_at | The lifecycle clock. |
They can't be removed or retyped. A fifth built-in, the profile's source_key, is not listed here: it is the key column chosen with the backing table, and that section is where you change it.
All four are computed exactly like a declared property. Each row's Source column shows the expression, or Not mapped, with Compute (or Edit) opening the same dialog described under Compute a property. That is what makes an account's email the email of its first user: choose First related row, the users table, the email column, and an order — rather than being limited to a column on the backing table.
Opening the dialog on an unmapped field prefills the obvious column when the table has one (email, name, created_at, and so on). It is a prefill: check it before you click Use expression. Clear unmaps the field; Signed up then falls back to the first sync time.
Built-in fields are saved with Save properties, alongside the rest of the set. A workspace with an additional source lists each mapped source on the row, the primary first, because an additional source computes its own Email or Domain to match rows to existing profiles.
Property types
| Type | Holds |
|---|---|
| Text | Any string. |
| Number | A numeric value. |
| Yes / no | A true or false value, shown as Yes or No. |
| Date | A point in time. |
| Choice | One of a fixed set of options. |
| JSON | Structured data, including a list of records. |
For a Choice property, list the allowed options comma-separated — free, pro, enterprise. Leave the options empty to accept any value while you're still deciding what the set should be.
A JSON property that holds a list of records — the first ten users on an account, say — renders as a small table on the profile page. It is there to read, not to filter on: a rule that needs "how many" reads a separate number property.
Property roles
The role records what a property is for:
- Signal (scored) — a value that measures something about the profile.
- Segment (filter) — a value you group or filter by, like a plan or a region.
- Metadata — kept for reference, not for decisions.
Roles decide which properties earn a column on the Profiles list: up to three appear, signals first, then segments, then metadata.
Mark personal data
Tick Contains personal data on any property holding something personal — a name, a phone number, a street address. Those properties are tagged PII wherever the value is shown, so anyone reading a profile can see at a glance which fields need care.
Compute a property
A property can be Manual — filled by hand or by an import that happens to carry the key — or computed from the backing row in your own database. Once the backing table is set, each property row's Source column offers Compute; until then it says Choose a backing table first. The built-in fields use the same dialog.
Pick one of four shapes:
| Shape | What it reads | Example |
|---|---|---|
| Column | A column on the backing table. | accounts.plan_tier |
| Joined value | A column on the row this one points at, through a foreign key. | The owner's email, via accounts.owner_id → users.id |
| First related row | A column on the first row that points back at this one, in an order you choose, optionally only rows matching a filter. | The email of the earliest user on an account, ordered by users.created_at |
| List | The first N rows that point back at this one, as a small table on the profile page. JSON type only. | The ten most recent users on an account |
Joined value and First related row are the two directions of the same relationship: use Joined value when the backing row holds the other row's key (an account's owner_id), and First related row when the other rows hold the backing row's key (each user's account_id) and there may be several. Without an order, the database picks which related row is first, so set one.
All three related shapes reach their table the same way: a path of one to three steps from the backing table, built step by step. Each step lists every table the schema's foreign keys can reach from the previous one, in both directions, with the join spelled out — users · users.account_id → accounts.id for the users on an account, users · accounts.owner_id → users.id for the account's owner — plus Another table — join by hand for a relationship the schema doesn't declare. A second step reaches nested ownership (the sessions of an account's users), and each step can carry its own filter. The column you read, the order and the list's columns are then picked off the table at the end of the path. It is the same builder usage metrics use. Every table and column comes from the schema Uptend read when the source was connected; nothing is typed free-form.
Click Preview to run the expression for the same five profiles the mapping preview shows. Each value is converted to the property's type exactly as a sync would — an unconvertible value is flagged rather than stored — and the planner's cost verdict for the statement appears underneath. Then Use expression, and Save properties to persist it with the rest of the set.
A List is for reading, not for rules. Counting related rows — projects created, orders placed, users seen this week — is not a property shape: it is a usage metric, declared once under Settings → Usage and tracked as a family of properties (total, first, last, and windowed counts). The dialog says so where a count used to be. Expressions run read-only in your database; nothing in Uptend can write to it.
Make manual in the same dialog removes the expression; the property keeps its stored values and stops being computed on the next sync.
Remove a property
Click the remove button on the property's row, then click Save properties.
Removing a property takes it off the workspace — it stops appearing on profiles and stops being filled by syncs — but the values already stored under it are kept. Dropping a property is usually a mapping correction, so if you declare the same key again later, the old values are simply there.
A handful of keys are reserved and can't be used for a property, because a
profile already has them: id, source_key, display_name, email,
domain, source_created_at, properties, profile_id, workspace_id,
created_at, and updated_at.
Choose the backing table
Pick the table whose rows become profiles, the column that identifies a row, and the column changes are detected by.
Track usage
Declare what a profile does in your application — projects created, orders placed, users invited — once, and get a family of properties that rules and scores can read.