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

# Contact fields

> The one catalog behind segments, personalization, import mapping and the contact profile: default fields, integration fields and the custom fields you create.

**Contact fields** are the properties a contact can hold. Every field in the workspace lives in one catalog, and that catalog is what the rest of Senderz reads.

The same list feeds the segment builder, the personalization picker in the email and SMS editors, the column dropdown on the import wizard, the Properties card on a contact, the automation steps that read or write a property, and the column picker when you export. Add a field once and it turns up everywhere.

## Where to find it

Go to **Settings**, then **AI & Automation**, then **Contact Fields**. The screen has two tabs: **Contact fields** and **Metrics**. This page is about the first one.

You can also reach it from a contact. Open any contact, find the **Properties** card, and click **Manage fields**.

## Three kinds of field

Every row in the table carries one of three badges. The badge decides what you are allowed to do with it.

<CardGroup cols={3}>
  <Card title="System" icon="lock">
    Built in. Email, phone, name, timezone, consent, tags, created date and the
    rest. You can fill the value on a contact, but the field itself cannot be
    renamed, retyped or deleted.
  </Card>

  <Card title="Integration" icon="plug">
    Comes from a connected store, reviews app or loyalty app. Managed by that
    integration, so it is read-only here. The row links straight to
    Integrations.
  </Card>

  <Card title="Custom" icon="wand-magic-sparkles">
    Fields you create. Rename them, change the value type, delete them. These
    are the only editable rows.
  </Card>
</CardGroup>

<Info>
  **An integration field only appears while that integration is connected.**
  Connect Shopify and the Shopify fields show up under a Shopify group.
  Disconnect it and they leave the catalog again. That is deliberate: listing a
  field nothing can fill would give you a filter that always returns nobody.
</Info>

## How the catalog is grouped

Fields are grouped in this order:

1. **Contact details** identity, address, consent and attribution
2. **Email & SMS activity** opens, clicks and other messaging history
3. **Tags**
4. **One group per connected integration**, named after the integration, in alphabetical order
5. **Custom fields**

Store, web activity, loyalty and reviews fields do not get generic groups. They sit under the integration that supplies them, so you can always tell where a value came from.

## Reading the table

| Column      | What it tells you                                                                                                      |
| ----------- | ---------------------------------------------------------------------------------------------------------------------- |
| Name        | The display label, used everywhere in the app.                                                                         |
| Field key   | The stable identifier. It never changes, and it is what merge tags and filters actually reference.                     |
| Value type  | Text, Number, Date, Yes / No, Select, Multi-select, List, Link, and the built-in types like Email, Phone and Currency. |
| Source      | System, Integration, Manual, CSV, or the name of the store the field came from.                                        |
| Used in     | How many segments, automations and templates reference this field.                                                     |
| Fill rate   | The share of your contacts that actually have a value.                                                                 |
| Last update | When a custom field's definition was last changed.                                                                     |

Above the table there is a counter showing the total plus a breakdown by kind, a search box that matches on name and key, filter pills for **All / System / Integration / Custom**, and a **Source** dropdown when you have more than one source.

### Fill rate

Fill rate is a real measurement, not an estimate. It is the percentage of contacts in the workspace that have a value in that field, recalculated when the page loads.

A dash instead of a number means no contact has ever had a value there. That is the honest signal that a field is offered but empty, and it is worth checking before you build a segment on it.

### Used in

Hover **Used in** to see exactly which segments, automations and templates reference the field, each one a link. This is the list you work through before deleting a field.

Deleted automations do not count. They are on a retention clock and are not reachable, so they never block you.

## Creating a field

<Steps>
  <Step title="Click New field">
    Top right of the Contact fields tab.
  </Step>

  <Step title="Type a field name">
    Use plain language, for example "Favourite category". Senderz shows the
    derived **field key** underneath as you type, in this case
    `favourite_category`. The key is lower case with underscores, at least two
    characters and at most 64.
  </Step>

  <Step title="Choose a value type">
    See the table below. Pick carefully: changing it later is possible but it
    has to be checked against every value you already stored.
  </Step>

  <Step title="Add options, for Select and Multi-select">
    Type each option and press Enter or comma. At least one is required.
  </Step>
</Steps>

You can also create a field without leaving the import wizard. On the mapping step, open the dropdown for any column and choose **+ Create new custom field**. Senderz suggests a value type from the sample values in that column, creates the field and maps the column to it in one go.

### The value types

| Type         | Accepts                                            | Notes                                                                                                    |
| ------------ | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Text         | Any text                                           | Up to 1,000 characters.                                                                                  |
| Number       | A number                                           | A value that is not a number is rejected rather than stored as text.                                     |
| Date         | An ISO-8601 date, `YYYY-MM-DD` or a full timestamp | `03/04/2024` is refused on purpose, because there is no safe way to know whether that is March or April. |
| Yes / No     | true, false, yes, no, 1, 0 and similar             | Stored as a real boolean.                                                                                |
| Select       | One of the options you defined                     | A value outside the option list is rejected.                                                             |
| Multi-select | Several of the options you defined                 | Same rule per value.                                                                                     |
| List         | Several free-text values                           | Up to 100 values, each up to 1,000 characters.                                                           |
| Link         | An http or https URL                               | Normalised, and refused if it is not a valid link.                                                       |

<Note>
  Because the type is enforced on write, a Date field really does hold dates and
  a Number field really does hold numbers. That is what lets the segment builder
  offer "before / after / in the last N days" on one and "greater than / between"
  on the other.
</Note>

## Editing a field

Custom rows have an edit button. You can change:

* **Display label** freely. It updates everywhere the field is shown.
* **Value type**, with a check first.
* **Options**, for Select and Multi-select.

The **field key cannot be changed after the field is created**. It is what every segment, merge tag and automation refers to, so changing it would silently break them.

### Changing a value type

When you change the type, Senderz re-checks the values you already stored, sampling up to 500 contacts, and tells you how many would not survive the change. It shows you the offending values before you commit.

If you confirm anyway, those values are not converted. They stay as they are and may stop matching filters that use the field. Confirm only when you have looked at the samples.

## Deleting a field

Custom rows have a delete button. You are asked to type the field key to confirm, because deleting a field also removes every contact's value for it and cannot be undone.

<Warning>
  **A field that is in use cannot be deleted.** If any segment, automation or
  template references it, the dialog switches to "Can't delete this field" and
  lists exactly which assets are blocking, each as a link. Remove the field from
  those first, then delete it.
</Warning>

The same rule applies to bulk delete. Select several custom fields, choose **Delete**, and the confirmation tells you how many are in use and will be kept.

Integration and system fields have no delete button at all.

## Where a field is usable

<AccordionGroup>
  <Accordion title="In segments" icon="filter">
    Every field that can be filtered on turns up in the segment builder's field
    picker, grouped the same way it is here. The operators you get depend on
    the value type:

    | Value type         | Operators                                                                                   |
    | ------------------ | ------------------------------------------------------------------------------------------- |
    | Text, Select, Link | is, is not, contains, does not contain, starts with, ends with, is set, is not set          |
    | Number             | equals, not equals, greater than, at least, less than, at most, between, is set, is not set |
    | Date               | before, after, between, in the last N days, is set, is not set                              |
    | Yes / No           | is, is not                                                                                  |
    | List, Multi-select | in, not in, is set, is not set                                                              |

    See [Segments](/en/audience/segments).
  </Accordion>

  <Accordion title="In email and SMS content" icon="envelope">
    Every field has a merge tag. Fields stored directly on the contact record
    use their own name, for example `{{firstName}}` or `{{email}}`. Everything
    else, including every field you create, uses the `custom.` prefix, for
    example `{{custom.favourite_category}}`.

    You do not have to type them. Use the personalization menu in the email
    editor or the variable picker in the SMS composer, both of which read this
    catalog. Set a fallback so a contact with no value still gets a sensible
    message.

    See [Templates](/en/messaging/templates).
  </Accordion>

  <Accordion title="On the import wizard" icon="file-import">
    The column dropdown on the mapping step is generated from this catalog, so
    what you see in Settings and what you see when importing are always the same
    list.

    Computed fields appear but are disabled, with a note saying so. Every column
    also offers **Don't import this column**, which is honoured as a real
    instruction: an ignored column is not auto-detected behind your back.

    See [Importing contacts](/en/audience/import).
  </Accordion>

  <Accordion title="On a contact" icon="address-book">
    The **Properties** card on a contact profile edits values inline. **Add
    property** opens a picker of everything that can be written. Computed fields
    show with a **Computed** badge and cannot be typed.

    See [Contacts](/en/audience/contacts).
  </Accordion>

  <Accordion title="In automations" icon="sitemap">
    Two steps read this catalog. **Update user properties** lets an automation
    set a property on a contact, with the input matching the value type. And a
    date-based trigger picks its anchor from your Date fields, which is how a
    birthday or a renewal-date automation is built.

    See [Steps](/en/messaging/flows/steps) and
    [Triggers](/en/messaging/flows/triggers).
  </Accordion>

  <Accordion title="On export" icon="file-export">
    The export column picker groups the same catalog and shows how many contacts
    actually have each field. Fields that are empty for every contact are tucked
    behind **Show N fields with no data**, with the explanation that they would
    export as blank columns. You can still pick them.
  </Accordion>
</AccordionGroup>

## Computed and read-only fields

Some fields are marked **Computed**. Senderz works the value out for you, so nobody can type it, import it or set it from an automation.

<Warning>
  Be careful with computed fields. A number of them are declared in the catalog
  but nothing populates them yet, so they read as permanently empty. The **fill
  rate** column is how you tell: a dash means no contact has ever had a value.
  Check it before you build a segment on a computed field, or the segment will
  match nobody.
</Warning>

Thirteen commerce and engagement fields are the exception. They are calculated at the moment you export, from your real event history, so they are populated in an export file even though they read as empty on a contact:

first active, last active, first email opened, last email opened, total messages opened, first message clicked, last message clicked, total messages clicked, first purchase, last purchase, total purchases, total spent and average order value.

## Aliases: why your file maps itself

Each built-in field carries a list of alternative names. "E-mail", "Email address", "Customer email" and the Hebrew equivalents all resolve to Email. Shopify's own column headers, and the `$`-prefixed keys other platforms export, resolve too.

That is why an export from another platform usually arrives with most columns already mapped on the import wizard. Always review the mapping before starting the import, but you rarely have to build it from nothing.

## Limits

| Limit                                 | Value                                       |
| ------------------------------------- | ------------------------------------------- |
| Field key                             | 2 to 64 characters, lower case, underscores |
| Display label                         | 255 characters                              |
| Options on a Select or Multi-select   | 100 options, each up to 80 characters       |
| Values in a List field                | 100                                         |
| Length of one stored value            | 1,000 characters                            |
| Values sampled when you change a type | 500                                         |

There is **no product cap on how many custom fields you can create**. A very high safety ceiling exists so a runaway import cannot create fields without bound, but it is far above any real catalog and you should never meet it.

## Related

<CardGroup cols={2}>
  <Card title="Segments" icon="filter" href="/en/audience/segments">
    Filtering on a field, and the operators each value type offers.
  </Card>

  <Card title="Contacts" icon="address-book" href="/en/audience/contacts">
    Editing property values on a single contact.
  </Card>

  <Card title="Importing contacts" icon="file-import" href="/en/audience/import">
    Mapping columns and creating a field inline.
  </Card>

  <Card title="Templates" icon="envelope" href="/en/messaging/templates">
    Merge tags and fallbacks.
  </Card>
</CardGroup>
