identify()
The identify() method links an anonymous app user to a known identity. Call it when the user logs in, registers, or updates their profile.
Syntax
iOS (Swift)
Datafly.shared.identify(userId: String, traits: [String: Any]? = nil)Android (Kotlin)
Datafly.identify(userId: String, traits: Map<String, Any>? = null)React Native / Cordova
Datafly.identify(userId, traits?)Flutter
await Datafly.identify(userId, traits: {...})Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | String | Yes | Unique, stable identifier (e.g., database ID) |
traits | Dictionary/Map | No | Key-value pairs describing the user |
Basic usage
// iOS -- after login
Datafly.shared.identify(userId: "user-123", traits: [
"email": "jane@example.com",
"name": "Jane Doe",
"plan": "professional",
])// Android -- after login
Datafly.identify("user-123", mapOf(
"email" to "jane@example.com",
"name" to "Jane Doe",
"plan" to "professional"
))How identity works on mobile
When identify() is called:
- The
userIdis stored in memory and included in all subsequent events - Traits are merged with previously set traits (new values overwrite existing keys)
- An
identifyevent is sent to your Signal endpoint - The server links
userIdto theanonymousId, creating a unified profile
Before identify():
anonymousId: "a1b2c3d4-..." (unknown user)
After identify("user-123"):
anonymousId: "a1b2c3d4-..." (linked)
userId: "user-123" (known user)All subsequent track() and screen() calls include both anonymousId and userId.
PII handling
Traits containing PII (email, name, phone) are hashed server-side using SHA-256 before delivery to vendor APIs. Raw PII is stored only in your own database. This enables Meta Advanced Matching, Google Enhanced Conversions, and TikTok matching without exposing user data.
Trait merging
Traits merge across multiple identify() calls:
// First call
Datafly.shared.identify(userId: "user-123", traits: ["email": "jane@example.com", "plan": "starter"])
// Later call -- plan updated, email preserved
Datafly.shared.identify(userId: "user-123", traits: ["plan": "professional"])
// Internal state: { email: "jane@example.com", plan: "professional" }Common traits
| Trait | Type | Description |
|---|---|---|
email | String | Email address |
name | String | Full name |
first_name | String | First name |
last_name | String | Last name |
phone | String | Phone number (E.164 format preferred) |
plan | String | Subscription plan or tier |
created_at | String | ISO 8601 date of account creation |
company | String | Company name |
Trait names are snake_case, the names every integration blueprint reads (first_name, last_name, address.postal_code). Earlier versions of this page showed camelCase names; Signal still accepts firstName, lastName, createdAt, dateOfBirth, jobTitle and address.postalCode and renames them to their snake_case form when the event arrives, so existing sites keep working. If you send both spellings of one trait, the snake_case value is used. Your own trait names are never renamed.
Use a stable, unique identifier as the userId (database primary key or UUID). Do not use email addresses as the userId — users may change their email. Pass email as a trait instead.