Define: Attribute Definition
The Define step controls how attributes are generated using Apache Velocity expressions, unique identifiers, UUIDs, or counters. This happens after Attribute Mapping (if sources are configured) and before Match scoring (for normal attributes).
When to use Attribute Definition
| Goal | Use Attribute Definition | Example |
|---|---|---|
| Generate unique usernames | Yes (Unique type) | jsmith, jsmith1, jsmith2 |
| Assign stable UUIDs | Yes (UUID type) | a3f2e8b4-7c2d-4f9e-8a1b-3c5d6e7f8g9h |
| Sequential employee numbers | Yes (Counter type) | 1000, 1001, 1002... |
| Computed attributes | Yes (Normal type with expression) | Full name from first + last; formatted dates |
| Normalize/format values | Yes (Normal type with expression + utilities) | Parse address, format phone, proper case names |
Global settings
| Field | Purpose | Recommended value |
|---|---|---|
| Maximum attempts for unique Define generation | Cap on retries for generating unique values | 100 (default); increase for large datasets with high collision risk (e.g. 200–500) |
Why this matters: For Unique type attributes, if the generated value already exists, the connector appends a counter and retries. This setting prevents infinite loops if the expression always produces the same value.
Per-attribute definition configuration
For each attribute you want to generate, add an Attribute Definition:
| Field | Type | Purpose | Options / Example |
|---|---|---|---|
| Attribute Name | String (required) | Name of generated attribute | username, uuid, employeeNumber, fullName, formattedHireDate |
| Apache Velocity expression | String (optional) | Template to compute value | #set($i=$firstname.substring(0,1))$i$lastname |
| Case selection | Dropdown (required) | Text case transformation | Do not change, Lower case, Upper case, Capitalize |
| Attribute Type | Dropdown (required) | Generation behavior | Normal, Unique, UUID, Counter-based |
| Counter start value | Integer | Starting number (Counter type) | 1, 1000, 50000 |
| Minimum counter digits | Integer | Zero-padding (Counter/Unique types) | 3 → 001, 002; 5 → 00001 |
| Maximum length | Integer (optional) | Truncate to this length | 20; counter preserved at end for Unique/Counter |
| Normalize special characters? | Boolean | Remove special chars/quotes | Yes for usernames/IDs |
| Remove spaces? | Boolean | Remove all whitespace | Yes for usernames/IDs |
| Refresh on each aggregation? | Boolean | Recalculate every run (Normal type only) | Yes if dynamic; No if stable |
Screenshot placeholder: Attribute Definition with examples. Attribute definition example
Attribute types explained
Normal type
Behavior: Standard computed attribute; recalculated based on Refresh on each aggregation? setting.
| Refresh setting | Behavior | Use case |
|---|---|---|
| Yes | Recalculated every aggregation | Dynamic values that should update (full name, age, formatted dates) |
| No | Calculated once; persisted | Stable values (initial assignment, one-time calculations) |
Examples:
# Full name (refresh: Yes)
$firstname $lastname
# Formatted hire date (refresh: No, unless hireDate changes)
$Datefns.format($hireDate, 'MMMM dd, yyyy')
# Years of service (refresh: Yes, dynamic)
$Math.floor($Datefns.differenceInDays($Datefns.now(), $hireDate) / 365)
Unique type
Behavior: Must be unique across all Fusion accounts; connector adds disambiguation counter on collision. Unique attributes are only computed when a Fusion account is first created or when an existing account is activated (an internal mechanism to reset unique attributes). They are not refreshed by Force Normal-type attribute refresh on each aggregation (located at Advanced Settings → Developer Settings; applies only to Normal-type attributes).
How it works:
- Generate value from expression
- Check if value exists on any account
- If unique → use value
- If collision → append counter (starting at 1), check again
- Repeat up to Maximum attempts
Counter format: {base value}{counter} (e.g. jsmith1, jsmith2)
Zero-padding: Use Minimum counter digits to pad counter (e.g. digits=3 → jsmith001)
$isUnique(value) helper: Unique definitions can call $isUnique(...) inside the Velocity expression to test whether a candidate value is currently free after the same trim/case/spaces/normalize/maxLength rules are applied. Use this to choose between candidate formats before the connector falls back to automatic $counter disambiguation.
Template safety note: Keep Velocity directives on separate lines (
#if,#else,#end,#set) to avoid parser ambiguities.
Examples:
Expression: #set($i=$firstname.substring(0,1))$i$lastname
Case: Lower case
Normalize: Yes
Spaces: Yes
Firstname="John", Lastname="Smith"
→ Generate: "jsmith"
→ Check: Already exists
→ Append counter: "jsmith1"
→ Check: Unique
→ Result: "jsmith1"
## Conditional candidate selection using $isUnique
#set($base = "$firstname.$lastname")
#set($alt = "$firstname$lastname")
#if($isUnique($base))
$base
#elseif($isUnique($alt))
$alt
#else
$base
#end
UUID type
Behavior: Generates immutable universally unique identifier (v4 UUID).
No expression needed: UUID is auto-generated; any expression is ignored.
Characteristics:
- Globally unique (extremely low collision probability)
- Immutable (never changes once generated)
- Format: 36 characters (8-4-4-4-12 hex digits)
- Example:
a3f2e8b4-7c2d-4f9e-8a1b-3c5d6e7f8a9b
Use cases:
- Native identity in ISC (stable reference that never changes)
- Account name when you need immutable identifier
- Cross-system correlation (UUID as common key)
Counter-based type
Behavior: Sequential incrementing number; each account gets next number in sequence.
How it works:
- Check highest existing counter value
- Next account gets: max + 1
- Counter state persisted across aggregations
Fields:
- Counter start value: First number in sequence (e.g. 1, 1000, 50000)
- Minimum counter digits: Zero-padding (e.g. 5 →
00001,00002)
Expression support: Counter type supports Velocity expression with special $counter variable:
# Employee number with prefix
EMP-$counter
Counter start: 1000, Digits: 5
→ EMP-01000, EMP-01001, EMP-01002
Apache Velocity context
The Apache Velocity expression field provides a powerful templating language with access to utilities and data.
Available data
| Source | What you can access | Example |
|---|---|---|
| Mapped account attributes | All attributes from Attribute Mapping | $jobTitle, $department, $email |
| Source account attributes | Direct source attributes (if no mapping) | $firstname, $lastname, $hireDate |
| Identity attributes | When Include identities = Yes | $identity.firstname, $identity.employeeNumber |
| $accounts | Managed account snapshots: source attributes plus _id (composite key sourceId::nativeIdentity), nested source (id, name — managed accounts only for id), nested schema (id = native identity, name = display name), and IIQDisabled. Top-level $originAccount is the same composite key for the origin row only. Ordered by configured source order, then account insertion order, then unknown sources. If mainAccount contains a valid managed account key, that account is moved to index 0. |
$accounts[0]._id, $accounts[0].source.name, $accounts[0].schema.name |
| $sources | Managed account snapshots grouped by source name | $sources.get("Workday") |
| $previous | Previous generated account state | $previous.username |
| $originSource | Source that originally created the Fusion account (when available) | Identities, Workday |
| $originAccount | String id of the identity or managed account that originally created the Fusion account (same as the originAccount attribute) |
Use as a scalar in expressions |
| $account | Snapshot for the origin only: same shape as $accounts[] entries when the origin is a managed account; when the origin is Identities and identity attributes are available, identity-backed fields are used first (then synthetic identity row if needed). Use $originAccount for the composite key or identity id string. Identity-backed rows use source.name = Identities (no source.id) and schema for display name and id (_id matches the identity id). |
$originAccount, $account.schema.name, $account.source.name |
| Special variables | $counter (Counter type only) |
$counter in expression for Counter type |
Available utilities
$Math (JavaScript Math object)
Standard mathematical operations ($Math.round(x), $Math.floor(x), $Math.ceil(x), $Math.max(a, b), $Math.min(a, b), $Math.abs(x)).
$Datefns (date-fns library)
Advanced date formatting and manipulation ($Datefns.format(date, format), $Datefns.addDays(date, n), $Datefns.differenceInDays(date1, date2), etc.).
$AddressParse (address parsing)
Parse and normalize US addresses ($AddressParse.getCityState(city), $AddressParse.parse(address)).
$Normalize (data normalization)
Standardize common data formats ($Normalize.phone(number), $Normalize.date(date), $Normalize.name(name)).
Normalize.phone also accepts an optional default country code for local numbers, for example: $Normalize.phone($phone, "GB"). If the phone string already includes an international prefix (for example +1), that explicit prefix is used instead of the default.
For ambiguous numeric dates, Normalize.date accepts an optional priority argument:
$Normalize.date($birthDate, "dd-MM-yyyy,MM-dd-yyyy") (default) or
$Normalize.date($birthDate, "MM-dd-yyyy,dd-MM-yyyy").
Order of operations
Understanding the sequence helps design correct configurations:
| Step | Phase | Action | Example |
|---|---|---|---|
| 1 | Attribute Mapping | Merge per mapping rules (MAP) | Map [title, jobTitle] → jobTitle, merge: first found → "Engineer" |
| 2 | Normal Define | Generate non-unique attributes from mapped data | Generate fullName from $firstname $lastname → "John Smith" |
| 3 | Match / Scoring | Compare normal attributes against existing identities | Normal attributes feed into Match scoring |
| 4 | Unique Define | Generate unique attributes with collision detection | Generate username from $firstname.$lastname → "jsmith" (or "jsmith1" on collision) |
Key insights:
- Normal attribute definitions run before Match matching. Their output is available to the scoring engine and to unique definitions.
- Unique attribute definitions run after all Match matching has completed (as a global pass over every account). They can reference normal attribute values but not the other way around.
- Attribute Definition expressions can reference attributes created by Attribute Mapping. Ensure mapped attributes exist before referencing in expressions.
nativeIdentity and account name immutability
The nativeIdentity (account identifier) and account name (display attribute) are set at creation time and never changed afterwards, even if an attribute definition would otherwise overwrite them.
- If you define a unique attribute that maps to the same schema attribute as the fusion identity attribute, it will only be generated once (at account creation). Subsequent aggregations and enable/disable cycles will not change it for identity-linked accounts.
- Use a UUID unique attribute as native identity when you need a truly immutable, stable reference.
Unique attribute reset on enable/disable
Use regular unique attribute schemas to define attributes you may want to change, like usernames or email aliases. Disabling and then re-enabling a Fusion account triggers a unique attribute reset:
- Disable: preserves all existing unique attribute values.
- Enable: resets and regenerates all unique attribute values, ensuring collision-free values after the account has been inactive.
Preventing Fusion account creation (empty nativeIdentity skip pattern)
One can purposely generate an empty nativeIdentity in conjunction with the "Skip accounts with a missing identifier" processing option to prevent specific managed accounts or identities from generating Fusion accounts.
- Define an attribute definition (normal or unique) that maps to the fusion identity attribute.
- Design the expression so it evaluates to an empty string for accounts you want to exclude.
- Enable "Skip accounts with a missing identifier" in Processing Control settings.
## Example: only generate identity for accounts with an email
#if($email && $email != "")
$email
#end