Docs

Identify users

Hollo works without sign-in: every install gets its own conversation. If your app has accounts, tell Hollo who the user is. You'll see their name and details in the inbox, and their conversation follows them to every device they sign in on.

Anonymous and identified users

Without identifyWith identify
The user shows as an anonymous device in the inbox.The user shows with their name and email.
Each install has its own conversation.One conversation per user, on every device they sign in.
History stays with that one device.History comes back when they sign in again.

Users never see a Hollo sign-in screen. Identifying them happens quietly in your code.

Identify after sign-in

Hollo.identify(
    id: user.id,          // your own user ID
    name: user.displayName,
    email: user.email
)

Call it:

  • right after the user signs in or signs up,
  • at launch, if they're already signed in, and
  • again whenever their name or email changes.

Calling it again with the same details does nothing, so it's fine to call on every launch.

Use a stable ID. The id should be the ID your backend uses for this account, and it should never change. Don't use an email address (people change them) or a device ID (people change phones).

name and email help your team reply. Pass what you have; you can leave either out.

In a SwiftUI app

If your app keeps the signed-in user in an observable model, identify whenever it changes:

struct RootView: View {
    @Environment(Session.self) private var session

    var body: some View {
        ContentView()
            .task(id: session.user?.id) {
                if let user = session.user {
                    Hollo.identify(id: user.id, name: user.displayName, email: user.email)
                } else {
                    Hollo.signOut()
                }
            }
    }
}

Add attributes

Attributes show up on the user's profile in your inbox, so you can help without asking. Use them for things your team checks often: plan, account age, or the user's ID in your billing system.

Hollo.attributes = [
    "plan": "Pro",
    "signed_up": "2026-09-14",
    "workspace_count": "3",
]
  • Values are short text. Convert numbers and dates to strings.
  • Use up to 20 keys. Keep key names lowercase with underscores, so they read well in the inbox.
  • Setting attributes replaces the previous set. To change one value, set the full dictionary again.
  • To clear them, set Hollo.attributes = [:].

Don't put anything secret in attributes: no passwords, tokens or payment details. Your whole team can see them.

Reserved keys

A few keys link the user to your subscription tools, so Hollo can match their subscription events to the right person once integrations ship:

KeySet it to
revenuecat_idThe user's app user ID in RevenueCat.
superwall_idThe user's ID in Superwall.
adapty_idThe user's customer user ID in Adapty.

Sign out

Hollo.signOut()

This clears the user, their attributes and the local copy of the conversation from the device. Their history stays safe in your inbox and comes back when they sign in again. After sign-out, the device is anonymous until you call identify again.

Call it on every path that ends a session: your sign-out button, an expired session, and switching accounts.

If the user is deleting their account rather than signing out, call Hollo.eraseUserData() instead. See Privacy and data.

Verified identity

Anyone can claim any user ID from inside an app. To make sure a user is really who they say, your server signs a short-lived token with your app's identity secret (from the dashboard), and the app passes it to Hollo.

Sign a token on your server

The token is a JWT signed with HS256. Its sub is the same ID you pass to identify. Keep it short-lived; 10 minutes is plenty.

// Node / TypeScript, for example in your API's /hollo-token route
import { SignJWT } from "jose";

const secret = new TextEncoder().encode(process.env.HOLLO_IDENTITY_SECRET);

export async function holloToken(userId: string) {
  return new SignJWT({})
    .setProtectedHeader({ alg: "HS256" })
    .setSubject(userId)
    .setIssuedAt()
    .setExpirationTime("10m")
    .sign(secret);
}

Only return a token for the user who is signed in on that request.

Pass it to Hollo

Hollo.identify(id: user.id, name: user.displayName, email: user.email)

let token = try await myServer.holloToken()
Hollo.verify(token: token)

Fetch a fresh token after sign-in and at each launch.

Require it, if you want

Verified users get a badge in the inbox. You can also switch on Only verified users can chat for an app. Then a user without a valid token sees a prompt to sign in instead of the message box.

Troubleshooting

The same person shows up twice in the inbox. You probably identified them with two different IDs, for example an email on one device and a user ID on another. Pick one stable ID and use it everywhere.

The inbox shows an old name or email. identify sends what you pass at that moment. When the user edits their profile, call it again with the new details.

Attributes don't update. Remember that setting attributes replaces the whole set. If two parts of your app set different keys, merge them into one dictionary first.