> ## Documentation Index
> Fetch the complete documentation index at: /llms.txt
> Use this file to discover all available pages before exploring further.

# User Onboarding & Visitor Mode

> Build the full onboarding funnel: anonymous browsing with visitor mode, authenticated login, profile setup, and session management.

> [!NOTE]
>
> **SDK v7.x** · Last verified March 2026 · iOS · Android · Web · Flutter

> **Speed run — just the code**
>
> ```typescript theme={null}
> // 1. Visitor login (anonymous, read-only)
> await Client.loginAsVisitor();
>
> // 2. Upgrade to authenticated user
> await Client.login({ userId: 'user-123', displayName: 'Jane' });
>
> // 3. Update the user profile
> await UserRepository.updateUser('user-123', {
>   displayName: 'Jane Doe',
>   description: 'Hello world!',
>   avatarFileId: 'uploaded-avatar-id',
> });
> ```
>
> Full walkthrough below ↓

> [!TIP]
>
> **Platform note** — code samples below use TypeScript. Every method has an equivalent in the iOS (Swift), Android (Kotlin), and Flutter (Dart) SDKs — see the linked SDK reference in each step.

A great onboarding funnel lets users browse before committing. social.plus supports three user types — visitors (anonymous, read-only), authenticated users (full access), and bots (crawler/SEO). This guide walks through the entire flow from first launch to complete profile.

```mermaid theme={null}
graph TD
    A[App launched] --> B{Has account?}
    B -->|No| C[Login as Visitor]
    B -->|Yes| D[Login with credentials]
    C --> E[Browse feeds read-only]
    E --> F{User taps write action}
    F --> G[Show signup prompt]
    G --> D
    D --> H[Session established]
    H --> I[Set up profile]
    I --> J[Full social experience]
    H --> K{Token expires?}
    K -->|Yes| L[Session handler renews]
    L --> H

    classDef action fill:#e1f5fe,stroke:#0288d1,color:#01579b
    classDef decision fill:#fff8e1,stroke:#f9a825,color:#f57f17
    classDef process fill:#f3e5f5,stroke:#7b1fa2,color:#4a148c
    classDef outcome fill:#e8f5e9,stroke:#388e3c,color:#1b5e20

    class A action
    class B,F,K decision
    class C,D,E,G,H,I,L process
    class J outcome
```

> [!NOTE]
>
> **Prerequisites**: SDK installed → [SDK Setup](/social-plus-sdk/getting-started/overview.md), plus an API key from the social.plus console. Production apps also need a backend server to generate auth tokens.

> [!NOTE]
>
> **After completing this guide you'll have:**
>
> * Visitor mode enabled so unauthenticated users can browse content
> * A smooth visitor → authenticated transition with session continuity
> * Profile setup step (display name, avatar) at first login

***

## Quick Start: Login as Visitor

Let users browse your app without creating an account:

```typescript TypeScript theme={null}
import { Client } from '@amityco/ts-sdk';

const client = Client.createClient('your-api-key', 'sg');

try {
  await Client.loginAsVisitor({ sessionHandler });
} catch (error) {
  console.error('Visitor login failed:', error);
}
```

Full reference → [Visitor Mode](/social-plus-sdk/getting-started/visitor-mode.md)

***

## Step-by-Step Implementation

**1. Initialize the SDK**

Create the client once at app startup. This must happen before any login call.

```typescript TypeScript theme={null}
import { Client } from '@amityco/ts-sdk';

const client = Client.createClient('your-api-key', 'sg');
```

Full reference → [Authentication](/social-plus-sdk/getting-started/authentication.md)

**2. Login as a visitor (anonymous browsing)**

Visitors get read-only access — they can view feeds, communities, and profiles but cannot post, comment, react, or follow. The SDK skips MQTT connections and push notification registration for visitors, saving resources.

```typescript TypeScript theme={null}
try {
  await Client.loginAsVisitor({ sessionHandler });
  console.log('Visitor login successful');
} catch (error) {
  console.error('Visitor login failed:', error);
}
```

Full reference → [Visitor Mode](/social-plus-sdk/getting-started/visitor-mode.md)

**3. Detect user type and gate write actions**

Check the current user type before allowing write operations. Show a signup prompt when visitors try to interact.

```typescript TypeScript theme={null}
import { Client, UserTypeEnum } from '@amityco/ts-sdk';

const userType = Client.getCurrentUserType();
if (userType === UserTypeEnum.VISITOR) {
  // Show signup/login prompt
  showSignupModal('Create an account to post');
}
```

Full reference → [Visitor Mode](/social-plus-sdk/getting-started/visitor-mode.md)

**4. Login with authentication**

After the user signs up or logs in through your auth system, call the authenticated login. In production, always pass an `authToken` generated by your backend.

```typescript TypeScript theme={null}
try {
  await client.login({
    userId: 'user-123',
    displayName: 'John Doe',
    authToken: 'token-from-your-backend', // Required in production
  }, sessionHandler);
  console.log('Login successful');
} catch (error) {
  console.error('Login failed:', error);
}
```

Full reference → [Authentication](/social-plus-sdk/getting-started/authentication.md)

**5. Observe session state changes**

Monitor the session lifecycle to show the right UI: loading spinner during `establishing`, navigate to app on `established`, re-auth prompt on `tokenExpired`.

```typescript TypeScript theme={null}
import { Client } from '@amityco/ts-sdk';

Client.onSessionStateChange((state: Amity.SessionStates) => {
  switch (state) {
    case 'established':
      navigateToApp();
      break;
    case 'tokenExpired':
      showTokenRefreshIndicator();
      break;
    case 'terminated':
      handleSessionTermination();
      break;
  }
});
```

Full reference → [Authentication](/social-plus-sdk/getting-started/authentication.md)

**6. Set up the user profile**

After first login, let users set their display name, bio, and avatar. The SDK auto-creates the user record on first login — this step updates it.

```typescript TypeScript theme={null}
import { UserRepository } from '@amityco/ts-sdk';

const { data: updatedUser } = await UserRepository.updateUser('userId', {
  displayName: 'Jane Smith',
  description: 'Loves hiking and photography',
});
```

Full reference → [Update User Information](/social-plus-sdk/core-concepts/user-management/user-operations/update-user-information.md)

**7. Implement session handler for token refresh**

In production, tokens expire. The session handler lets the SDK request a fresh token from your backend without interrupting the user.

```typescript TypeScript theme={null}
const sessionHandler: Amity.SessionHandler = {
  sessionWillRenewAccessToken: async (renewal: Amity.AccessTokenRenewal) => {
    try {
      const newToken = await AuthService.refreshToken();
      renewal.renewWithAuthToken(newToken);
    } catch (error) {
      renewal.unableToRetrieveAuthToken();
    }
  },
};
```

Full reference → [Authentication](/social-plus-sdk/getting-started/authentication.md)

**8. Secure logout**

Always call `secureLogout()` when the user logs out. This clears the session, stops real-time connections, and unregisters push tokens.

```typescript TypeScript theme={null}
await Client.secureLogout();
```

Full reference → [Authentication](/social-plus-sdk/getting-started/authentication.md)

***

## Connect to Moderation & Analytics

> **Visitor analytics**
>
> Track how many visitors browse vs. convert to authenticated users. Visitor device IDs are available via `client.getVisitorDeviceId()` for analytics attribution.

> **Bot mode for SEO**
>
> Use `Client.loginAsBot()` for search engine crawlers to index public content. Bots have even more restricted permissions than visitors — they can only read, never interact.
>
> → [Visitor Mode — Bot Users](/social-plus-sdk/getting-started/visitor-mode.md)

> **Webhook: user created**
>
> Receive a `user.created` webhook event when a visitor converts to an authenticated user (first login). Use this to trigger welcome emails or onboarding flows.
>
> → [Webhook Events](/analytics-and-moderation/social+-apis-and-services/webhook-event.md)

***

## Common Mistakes

> [!WARNING]
>
> **Hardcoding auth tokens in client-side code** — Auth tokens should be generated server-side. Embedding them in your app exposes them to extraction.
>
> ```typescript theme={null}
> // ❌ Bad — token in source code
> await Client.login({ userId: 'u1', authToken: 'hardcoded-secret' });
>
> // ✅ Good — fetch token from your backend
> const { authToken } = await yourServer.getAmityToken(currentUser.id);
> await Client.login({ userId: currentUser.id, authToken });
> ```

> [!WARNING]
>
> **Skipping the session handler** — Without a session handler, expired sessions silently fail. Always implement `sessionHandler` to detect token expiry and re-authenticate.

> [!WARNING]
>
> **Calling write APIs as a visitor** — Visitors are read-only. Attempting to create posts or reactions as a visitor throws a permission error. Gate write actions behind an authentication check.

## Best Practices

> **Conversion funnel**
>
> * Show a subtle "Sign up for full access" banner while visitors browse — don't block the experience
> * Track which actions visitors attempt most (post, react, comment) to optimize your signup prompt placement
> * Pre-fill the display name from your auth provider so users don't have to type it twice
> * Gate write actions at the UI layer (disable buttons) rather than catching SDK errors

> **Security**
>
> * **Never ship without auth tokens in production** — without them, anyone can impersonate any `userId`
> * Use `secureLogout()` on every logout path (manual logout, session expiry, account deletion)
> * Implement the session handler — without it, sessions will fail silently when tokens expire
> * Store auth tokens server-side and pass them to the client at login time; never generate tokens client-side

> **Performance**
>
> * Visitors skip MQTT connections and push notification registration automatically — no extra optimization needed
> * Cache the user type check result per session; `getCurrentUserType()` is synchronous and fast
> * For SSR/SEO, use bot mode to pre-render public content without consuming authenticated user slots

***

> [!TIP]
>
> **Dive deeper**: [Getting Started Reference](/social-plus-sdk/getting-started/overview.md) has full parameter tables, method signatures, and platform-specific details for every API used in this guide.

## Next Steps

> **[Your next step → Build a Social Feed](/use-cases/social/build-a-social-feed.md)**
>
> Users can sign in — now give them a feed full of content to explore.

Or explore related guides:

> **[User Profiles & Social Graph](/use-cases/social/user-profiles-and-social-graph.md)**
>
> Build the profile page your new users land on

> **[Build a Social Feed](/use-cases/social/build-a-social-feed.md)**
>
> Show the feed that visitors browse before signing up

> **[Notifications & Engagement](/use-cases/social/notifications-and-engagement.md)**
>
> Set up push notifications after first login


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.