For the complete attribute type system and structure, see Attribute Types and The Normalization Model.
Before you begin
Answer these three questions before proposing a new attribute:- Does this attribute already exist? Search by aliases, descriptions, and examples---not just names. An attribute called
purchase_channelmight already cover what you plan to namebuy_source. - Is the meaning unambiguous? If two reasonable interpretations exist, you need two attributes, not one fuzzy compromise.
- Do you have real demand? At least two concrete use cases from different parties should need this attribute.
Naming your attribute
Thename field uses the pattern <attribute>[.<qualifier>]. Names should be specific enough to understand without additional context.
| Good | Bad | Why bad |
|---|---|---|
email | address | Ambiguous---postal or email? |
email.hashed_sha256 | hashed_value | Hashed what? |
total_amount.gross | total | Total of what? |
purchase_channel | channel | Marketing channel? Distribution channel? |
birth_year | year | Year of what event? |
display_name field is the human-readable label shown in UIs. It should be concise but clear---for example, "Email (SHA-256 Hash)" for the attribute named email.hashed_sha256.
Writing the description
The description is the most important piece of documentation for an attribute. A good description eliminates ambiguity for anyone creating mappings. Bad:Email addressGood:
The electronic mail address associated with an individual, formatted per RFC 5321, representing a point of contact for that person. Does not include addresses associated with businesses, roles, or distribution lists.Your description should answer:
- What does this attribute represent? Define the concept precisely.
- What does it explicitly NOT represent? Call out common confusions. If
emaildoes not include business or role addresses, say so. - What does null mean? Distinguish between unknown (data was not collected), not applicable (concept does not apply to this record), and intentionally blank (value was collected but is empty).
Join key designation
Setis_join_key to true if the attribute is suitable for identity resolution or record linkage. Only primitive types can be join keys.
Choosing a type
Select the type that most accurately represents the attribute’s semantics. Do not default tostring when a more specific type exists.
| Type | Use when | Examples |
|---|---|---|
string | Text values, identifiers, codes | Names, hashed emails, country codes |
boolean | True/false flags | Opt-in status, active/inactive |
double | Decimal numbers, measurements, currency amounts | Price, latitude, temperature |
long | Integers, counts, whole-number IDs | Age, row counts, sequence numbers |
timestamptz | Points in time (always with timezone) | Event timestamps, signup dates |
array | Repeated values of a single type | Interest categories, identifier lists |
object | Nested structure with named properties | Addresses, coordinates, composite identifiers |
enum: Use when the attribute has a closed set of allowed values. Add anenumarray to astringtype.validations: Use to enforce the canonical format (length constraints, range bounds, patterns).
items. For objects, define the field structure in properties and list mandatory fields in required.
See the Attribute Types Reference for full type definitions and examples.
Enum governance
When your attribute uses anenum, define each value with clear semantics. Every enum value should be a deliberate, documented choice---not an afterthought.
Example: purchase channel
| Value | Meaning | Common source mappings |
|---|---|---|
in_store | Purchase at a physical retail location | ”retail”, “brick_and_mortar”, “pos”, “1” |
online_web | Purchase via a web browser | ”web”, “ecommerce”, “website”, “2” |
online_app | Purchase via a native mobile app | ”app”, “mobile_app”, “mobile”, “3” |
other | Purchase through a channel not listed above | Any unrecognized value |
unknown | Purchase channel was not collected or is unavailable | NULL, empty string, “N/A” |
Enum rules
- Case-sensitive and lowercase. All enum values use
snake_case. - Always include fallback values. Use
otherwhen the source value is known but does not match any defined option. Useunknownwhen the source value is missing or indeterminate. - Document when to use
othervs.unknown.othermeans “we know the value but it doesn’t fit our categories.”unknownmeans “we don’t have the information.”
Using references
Use$ref with a numeric attribute ID when an object property should conform to an existing attribute’s definition. References avoid duplicating validation rules and semantics, and changes to the referenced attribute propagate automatically.
timestamp inherits the full definition of the event_timestamp attribute (ID 1007) and channel inherits from purchase_channel (ID 250), including their types, validations, and enum constraints.
See Reference Type for full details.
Setting collaborators
Thecollaborators property controls which companies can view or map to your attribute. Use it for organization-specific attributes shared with selected partners.
collaborators is omitted, the attribute follows default visibility rules for your organization.
Documenting beyond the schema
The schema defines structure. Documentation captures intent. Include the following alongside your attribute definition to help others create accurate mappings.Good examples
Provide 3—5 real values with context explaining why they belong:"[email protected]"--- a personal email address (valid)"[email protected]"--- plus-addressed email (valid, the plus suffix is part of the address)"[email protected]"--- a role address (invalid for this attribute; use a business email attribute instead)
Anti-examples
Values that do NOT belong and where they should go instead:"not-an-email"--- fails format validation, should be null"[email protected]"--- role address, belongs inbusiness_emailattribute""(empty string) --- should be null, not empty
Mapping guidance
Document common source representations and the expected transformations:- Email: Lowercase, trim whitespace, validate against pattern
$this LIKE '%@%.%' - Phone: Convert to E.164 format (e.g.,
+15551234567), strip parentheses, dashes, and spaces - Currency: Decimal with two-digit precision, strip currency symbols and thousands separators
Canonical representation
For ambiguous types, specify the expected serialization:- Timestamps: ISO 8601 in UTC (
2024-01-15T14:30:00Z) - Decimals: Precision expectations (e.g., currency amounts use two decimal places)
- Booleans:
true/false(not1/0, not"yes"/"no")
Validation checklist
Before submitting a new attribute, verify:nameis unambiguous without additional contextdescriptionexplains what it means AND what it does not meantypeis appropriate (not just defaulting tostring)enumvalues are defined with clear semantics (if applicable)validationsenforce the canonical format (if applicable)is_join_keyis set correctly for identity attributes- The attribute can be mapped from at least 2—3 real datasets
- No existing attribute already covers this concept
Recommended governance workflow
The following workflow is a recommended team process for introducing new attributes. It is not enforced by the platform.Proposal
A champion creates a specification using this guide. The spec includes the full attribute definition, description, examples, anti-examples, and mapping guidance.
Triage
Review the proposal for duplicates, ambiguity, and overly company-specific scope. If the attribute only makes sense for one organization, it may belong as an organization attribute rather than a shared one.
Draft
Create the attribute with limited
collaborators access. This restricts visibility while the attribute is being validated.Validation
Prove mapping feasibility by mapping the attribute across at least two real datasets. Confirm that the type, enum values, and validations work with actual source data.
Design principles
- Names are presentation, not identity. The
idis immutable;nameanddisplay_namecan evolve. - Separate semantics from syntax.
descriptioncaptures meaning;type,enum, andvalidationscapture structure. - Prefer two specific attributes over one vague one. Ambiguity is a bug, not a feature.
- Every attribute is maintenance burden. Only create what has real, demonstrated demand.
- Use references to avoid duplication. If a property should match an existing attribute, use
$ref.

