User Identification
Identify users in your app for personalized experiences.
User Identification
Identifying users is how you connect the people using your app to the targeting and personalization features in Setgreet. Once a user is identified, you can target them with flows based on their attributes, personalize content with their data, and track their behavior across sessions.
The identifyUser call
The identifyUser method sets the current user's ID and optional attributes. Call it whenever you know who the user is -- typically after login or signup.
// iOS
Setgreet.shared.identifyUser(userId: "user_123", attributes: [
"email": "jane@acme.com",
"plan": "pro",
"signupDate": "2026-01-15"
])// Android
Setgreet.identifyUser("user_123", mapOf(
"email" to "jane@acme.com",
"plan" to "pro",
"signupDate" to "2026-01-15"
))// React Native
import { identifyUser } from '@setgreet/react-native-sdk';
identifyUser('user_123', {
email: 'jane@acme.com',
plan: 'pro',
signupDate: '2026-01-15',
});// Flutter
await Setgreet.identifyUser(
"user_123",
attributes: {
"email": "jane@acme.com",
"plan": "pro",
"signupDate": "2026-01-15",
},
);The userId should be a stable, unique identifier from your system -- the same ID you use in your database or authentication provider. Do not use ephemeral identifiers like session tokens.
Anonymous users
Before identifyUser is called, the SDK assigns an auto-generated anonymous ID to the device. This allows Setgreet to:
- Display flows that do not require user targeting (for example, a generic welcome screen).
- Track flow analytics for unidentified users.
- Associate pre-identification behavior with the user once
identifyUseris called.
The anonymous ID is a UUID stored on the device and persists across app launches until resetUser is called.
Every SDK exposes the anonymous ID if you need it for server-side correlation:
// iOS
let anonId = Setgreet.shared.anonymousId// Android
val anonId = Setgreet.anonymousId// React Native
import { getAnonymousId } from '@setgreet/react-native-sdk';
const anonId = getAnonymousId();// Flutter
final anonId = await Setgreet.anonymousId;In React Native, getAnonymousId works on iOS from React Native SDK 1.7.0.
Updating attributes
You can call identifyUser multiple times with the same userId to update attributes. By default each call merges the new attributes with the existing ones rather than replacing the full set. An optional operation parameter (create or update) lets you control this explicitly.
// Update a single attribute after a plan change
Setgreet.shared.identifyUser(userId: "user_123", attributes: [
"plan": "enterprise"
])This is useful for keeping Setgreet in sync when user properties change mid-session (for example, after a plan upgrade or a profile update). If a flow should reflect the change, see Identify before showing a flow.
Language
Setgreet shows each flow in the user's language, whether or not the user is identified. Translations are added in the dashboard (see Localization); the SDK decides which language to ask for.
Your app's language setting
If your app lets users pick a language (for example in an in-app language picker), pass that choice to setLocale:
// iOS
Setgreet.shared.setLocale("tr-TR")
Setgreet.shared.setLocale(nil) // follow the device language again// Android
Setgreet.setLocale("tr-TR")
Setgreet.setLocale(null) // follow the device language again// React Native
import { setLocale } from '@setgreet/react-native-sdk';
setLocale('tr-TR');
setLocale(null); // follow the device language again// Flutter
await Setgreet.setLocale('tr-TR');
await Setgreet.setLocale(null); // follow the device language againThe value is a language tag such as "tr-TR", "pt-BR" or "de". An invalid value is ignored and the previous language is kept.
setLocale is a device setting, not a user attribute:
- It is saved on the device and survives app relaunches and
resetUser. - It is never stored on the user.
- It can be called before
initialize. - Passing
null(nilon iOS) removes it, and the order below applies again.
The locale passed to identifyUser
identifyUser also takes an optional locale. Setgreet saves it for the user only when you pass one. When you leave it out, no locale is sent and the language already saved for the user, if any, is kept. The device language is never stored on the user.
// iOS
Setgreet.shared.identifyUser(
userId: "user_123",
attributes: ["plan": "pro"],
locale: "es-MX"
)// Android
Setgreet.identifyUser(
userId = "user_123",
attributes = mapOf("plan" to "pro"),
locale = "es-MX"
)// React Native
import { identifyUser } from '@setgreet/react-native-sdk';
identifyUser('user_123', { plan: 'pro' }, 'create', 'es-MX');// Flutter
await Setgreet.identifyUser(
'user_123',
attributes: {'plan': 'pro'},
locale: 'es-MX',
);Use this when the language is part of the user's account in your system, so it follows them to other devices.
Which language is shown
Setgreet uses the first of these that is set:
- The
setLocalevalue on this device. - The
localepassed toidentifyUserfor the current user in this session. - The locale saved for the user at an earlier
identifyUser. - The device language.
If the flow has no translation for that language, it is shown in the flow's base language.
Anonymous users (never identified) get flows in their device language, or in the setLocale value if you set one.
Reset
Call resetUser when the user logs out. This clears the identified user and generates a new anonymous ID.
// iOS
Setgreet.shared.resetUser()// Android
Setgreet.resetUser()// React Native
import { resetUser } from '@setgreet/react-native-sdk';
resetUser();// Flutter
Setgreet.resetUser();After resetUser, the SDK behaves as if it is a fresh, unidentified device. Call identifyUser again when the next user logs in.
Always call resetUser on logout. If you skip this step and a second user logs in on the same device, flows may be
shown based on the previous user's attributes.
When to identify
| Moment | Why |
|---|---|
| After login | The most common place. You know the user ID and can pass current attributes. |
| After signup | Identify the user immediately after account creation so onboarding flows can be personalized. |
| When attributes change | Call identifyUser again with updated attributes so trigger conditions, Condition nodes, and variable bindings reflect the latest data. |
| On app launch (if already authenticated) | If the user is still logged in from a previous session, re-identify on launch to ensure the SDK has fresh attributes. |
Identify before showing a flow
Trigger conditions and Condition nodes are decided on Setgreet's servers from the attributes stored for the user at the moment the flow is requested. Call identifyUser before showFlow, so the flow is decided for the right user with their latest attributes. A flow that the identifyUser call itself brings up is decided with the attributes from that call.
On SDK versions up to 1.3.0, identifyUser sends its update in the background and returns before Setgreet has stored
the attributes. A showFlow or trackEvent called right after it can reach Setgreet first and be decided on the
attributes stored before that call. That can mean the previous or anonymous user. It also applies when you call
identifyUser again for the same user to update attributes: a flow shown right after a plan upgrade can still be
decided with the old plan. Identify at login or on app launch, and send attribute updates when the data changes, not
in the same moment as the call that shows the flow. Later SDK versions wait for a pending identifyUser before these
calls, but only for a short time, so an identifyUser that takes longer than that can still arrive after them.
What counts as an MAU
Each unique userId (or anonymous ID if the user is not identified) that triggers at least one SDK request during a billing period counts as one Monthly Active User (MAU) for billing purposes. Calling identifyUser itself does not consume additional MAU -- the user is counted once per billing period regardless of how many times identifyUser is called.