Contact Management
Identify users, update user properties and contacts, and track events.
This guide covers setting user identity (uid, emailId), attaching profile properties and contacts, tracking screen views and custom events, and updating location.
On this page
- Update user properties
emailIdvsemailZTContactAdditionalInfo- Starting and clearing the user identity session
- App Set ID, Advertisement ID, and push tokens
- Location tracking
- Unique client ID
- Event tracking
Update user properties
The ZTUserManager interface, exposed via ZetaClient.user, performs user operations. Update user data using the builder pattern or by calling updateUser().
ZetaClient.user.builder()
.setUid("uid")
.setFirstName("User1")
.setLastName("last-name")
.setName("name")
.setSignedUpAt("2024-09-17T05:54:58.000Z")
.setSource("source")
.setEmail(ZTUserEmail(email = "[email protected]"))
.setEmailId("[email protected]")
.setPhone(ZTUserPhone(phone = "1234"))
.setAdditionalProperties(mapOf(
"zt_test_string" to "zt_test_value",
"zt_test_number" to 123,
"zt_test_boolean" to true,
"zt_test_array" to listOf("zt_test_value1", "zt_test_value2"),
"zt_test_dict" to mapOf("key" to "value")
))
.submit()
ZetaClient.INSTANCE.getUser().builder()
.setUid("uid")
.setFirstName("User1")
.setLastName("last-name")
.setName("name")
.setSignedUpAt("2024-09-17T05:54:58.000Z")
.setSource("source")
.setEmail(new ZTUserEmail("[email protected]"))
.setEmailId("[email protected]")
.setPhone(new ZTUserPhone("1234"))
.setAdditionalProperties(Map.of(
"zt_test_string", "zt_test_value",
"zt_test_number", 123,
"zt_test_boolean", true
))
.submit();
You can also create a ZTUser object and call updateUser():
val user = ZTUser(name = "John Wick")
ZetaClient.user.updateUser(user)
ZTUser user = new ZTUser();
user.setName("John Wick");
ZetaClient.INSTANCE.getUser().updateUser(user);
emailId vs email
emailId vs emailemailId— use when the email should be treated as the unique identifier for the user. This populates the Email field under ZMP Identifiers (as well as the Contact for this email).email— use when you want to add the email as a contact with additional properties (preferences, subscription status). This populates the Contact section.
Important: If the
uidis set as an email address in the samebuilder()...submit()call, theemailIdvalue is ignored.
ZTContactAdditionalInfo
ZTContactAdditionalInfoFor contacts (email, phone), you can attach additional properties:
val additionalInfo = ZTContactAdditionalInfo().apply {
subscriptionStatus = ZTContactSubscriptionStatus.ACTIVE
inactivityReason = "reason"
signedUpAt = "2024-09-17T05:54:58.000Z"
lastOpened = "2024-09-17T05:54:58.000Z"
doubleOptInStatus = "single"
phoneType = "mobile"
lastSent = "2024-09-17T05:54:58.000Z"
lastClicked = "2024-09-17T05:54:58.000Z"
properties = mapOf("key" to "value")
}
ZetaClient.user.builder()
.setEmail(ZTUserEmail(email = "[email protected]", additionalInfo = additionalInfo))
.submit()
ZTContactAdditionalInfo info = new ZTContactAdditionalInfo();
info.setSubscriptionStatus(ZTContactSubscriptionStatus.ACTIVE);
info.setInactivityReason("reason");
info.setSignedUpAt("2024-09-17T05:54:58.000Z");
info.setLastOpened("2024-09-17T05:54:58.000Z");
info.setDoubleOptInStatus("single");
info.setPhoneType("mobile");
info.setProperties(Map.of("key", "value"));
ZetaClient.INSTANCE.getUser().builder()
.setEmail(new ZTUserEmail("[email protected]", info))
.submit();
ZTContactAdditionalInfo properties
ZTContactAdditionalInfo properties| Property | Type | Description |
|---|---|---|
preference | List<String> | Optional. Defaults to ["standard"] if not provided. |
subscriptionStatus | ZTContactSubscriptionStatus | Contact's subscription state. Supported values: NEW, ACTIVE, INACTIVE, NONE. |
inactivityReason | String | Optional. Reason the contact became inactive. |
signedUpAt | String | Optional. ISO 8601 date-time when the contact signed up. |
lastOpened | String | Optional. ISO 8601 date-time when the contact last opened a message. |
doubleOptInStatus | String | Optional. "single" or "double". |
phoneType | String | Optional. "mobile" or "landline". |
lastSent | String | Optional. ISO 8601 date-time when a message was last sent to the contact. |
lastClicked | String | Optional. ISO 8601 date-time when the contact last clicked a message. |
properties | Map<String, Any> | Optional. Additional custom contact properties. |
Notes
- All date-time values must be in ISO 8601 format, UTC.
preferenceof a contact defaults tostandard. Other preferences can be added or customized inside ZMP Settings; only values defined there may be passed inpreference.double_opt_in_statusis optional. Defaultnull; acceptssingleordouble.phone_typeis optional. Defaultnull; acceptsmobileorlandline.- The snake_case names above refer to JSON payload keys; the corresponding Kotlin properties use camelCase (
doubleOptInStatus,phoneType). additionalPropertiesonZTUseraccepts arbitrary key-value pairs and appears under the User Properties section in ZMP.
Starting and clearing the user identity session
The SDK tracks user session-specific properties and events. Setting uid or emailId starts the session.
ZetaClient.user.builder()
.setUid("uid")
.setEmailId("[email protected]")
.submit()
ZetaClient.INSTANCE.getUser().builder()
.setUid("uid")
.setEmailId("[email protected]")
.submit();
Note:
emailIdis ignored if theuidis also an email address.
Clear the identity session when the user changes inside your app:
ZetaClient.user.clear()
ZetaClient.INSTANCE.getUser().clear();
Note: Call
clear()whenever the user profile changes in your app (sign-out, account switch, etc.).
App Set ID, Advertisement ID, and push tokens
Pass device identifiers to the SDK to enhance user identification.
ZetaClient.user.setAppSetId(appSetId)
ZetaClient.user.setAdvertisementId(advertisementId)
ZetaClient.user.updatePushToken(token)
ZetaClient.INSTANCE.getUser().setAppSetId(appSetId);
ZetaClient.INSTANCE.getUser().setAdvertisementId(advertisementId);
ZetaClient.INSTANCE.getUser().updatePushToken(token);
Note: The App Set ID is scoped to the developer's apps on the device and does not require user consent. The Advertisement ID (GAID) requires user consent under relevant privacy frameworks.
Location tracking
trackLocation() accepts latitude, longitude, and a foreground/background flag. The location is cached in memory and attached to subsequent events as a property.
ZetaClient.user.trackLocation(
latitude = 12.933663251837913,
longitude = 77.62168405034637,
isForeground = true
)
ZetaClient.INSTANCE.getUser().trackLocation(
12.933663251837913,
77.62168405034637,
true
);
Unique client ID
The SDK supports host apps providing a unique_client_id to ZMP. Before using it, review these conditions:
- No two profiles may have the same
unique_client_idname:value pair. If a profile is updated with aunique_client_idmatching another profile, the profiles are merged. - A
unique_client_idpair is discarded if the same key already exists with a different value. - Enabling support for a unique client ID requires site-configuration updates. Coordinate with your account team to ensure the configuration is correct. Using an incorrect or mismatched client ID name may result in errors.
ZetaClient.user.setUniqueClientId(name = "key_name", value = "value")
ZetaClient.INSTANCE.getUser().setUniqueClientId("value", "key_name");
Event tracking
Auto-tracked events
| Event | When fired |
|---|---|
app_installed | First launch only. |
app_opened | App transitions from background to foreground. |
app_closed | App transitions from foreground to background. |
Note:
app_terminatedis an iOS-only lifecycle event. The Android SDK does not fire this event.
Screen name tracking
Use trackScreenName() to track screen navigation. The provided screen name is cached in memory and attached to subsequent events as a property.
ZetaClient.event.trackScreenName(
screenName = "Events Screen",
deeplink = "app://home",
properties = mapOf("screen" to "Home")
)
ZetaClient.INSTANCE.getEvent().trackScreenName(
"Events Screen",
"app://home",
Map.of("screen", "Home")
);
Custom events
Send a custom event by passing a name and a map of properties. Properties must be JSON-encodable.
ZetaClient.event.send(
eventName = "EventTest",
properties = mapOf(
"events-array" to listOf("screen1", "screen2"),
"events-dict" to mapOf("screen" to "events")
)
)
ZetaClient.INSTANCE.getEvent().send(
"EventTest",
Map.of(
"events-array", List.of("screen1", "screen2"),
"events-dict", Map.of("screen", "events")
)
);
Date-time formatting
All date-time values sent as event properties or user properties must be in ISO 8601 format with UTC timezone:
2024-09-17T05:54:58.000Z
The SDK exposes a formatDateToIso() extension on Long that converts a millisecond timestamp to this format:
import net.zetaglobal.app.zetacore.common.ZTDeviceUtil.formatDateToIso
val iso = System.currentTimeMillis().formatDateToIso()
// e.g. "2024-09-17T05:54:58.000Z"
import net.zetaglobal.app.zetacore.common.ZTDeviceUtilKt;
String iso = ZTDeviceUtilKt.formatDateToIso(System.currentTimeMillis());
// e.g. "2024-09-17T05:54:58.000Z"
Next
- Push Notifications — Firebase integration, notification config, deep linking.
- In-App Messaging — foreground messages and email collection.
- App Inbox — a persistent, queryable message store.
- User Guide: User Properties — standard and custom properties in ZMP.
- User Guide: Identity Resolution — how profiles merge.
See also
- Platform support -- feature availability by platform and SDK version.
