Skip to main content
This guide will help you to create a user profile inside your own custom UI, including everything you see in the regular Dynamic Widget UI component/Dynamic Embedded Widget UI component described above.

Setup

Show the user’s profile based on whether they are logged in or not

How: Check if the user is logged in or not Hook/Component: useIsLoggedIn Notes: We start here assuming you have signup/login implemented already

Profile Info

Show user profile information

How: Fetch info from user object on useDynamicContext Hook/Component: useDynamicContext Notes: The format of the user can be found here: userProfile. For working with custom metadata fields and storing additional user data, see User Metadata.

Allow user to update their profile information

How: client.auth.updateUser and client.auth.verifyUserUpdateOtp Method: client.auth.updateUser Notes: updateUser returns flags to indicate whether OTP is required for the change (isEmailVerificationRequired and isSmsVerificationRequired). Available from v4.38.0.

Updating Email

React Native
import { client } from './dynamicClient';
import { useState } from 'react';

const [showVerifyEmailForm, setShowVerifyEmailForm] = useState(false);
const [loading, setLoading] = useState(false);

const onSubmitEmailUpdate = async (firstName: string, email: string, metadata?: Record<string, any>) => {
  try {
    setLoading(true);
    // OTP is automatically sent to the new email when updateUser is called
    const result = await client.auth.updateUser({ firstName, email, metadata });
    if (result.isEmailVerificationRequired) setShowVerifyEmailForm(true);
  } finally {
    setLoading(false);
  }
};

const onVerifyEmailFormSubmit = async (verificationToken: string) => {
  try {
    setLoading(true);
    await client.auth.verifyUserUpdateOtp(verificationToken);
  } finally {
    setLoading(false);
    setShowVerifyEmailForm(false);
  }
};

// Resend if needed
const resendEmailOtp = async () => {
  await client.auth.email.resendOTP();
};

Updating Phone

React Native
import { client } from './dynamicClient';
import { useState } from 'react';

const [showVerifySmsForm, setShowVerifySmsForm] = useState(false);
const [loading, setLoading] = useState(false);

const onSubmitPhoneUpdate = async (firstName: string, phoneNumber: string, metadata?: Record<string, any>) => {
  try {
    setLoading(true);
    // phoneNumber should be E.164 format, e.g. +14155551234
    // OTP is automatically sent to the new phone when updateUser is called
    const result = await client.auth.updateUser({ firstName, phoneNumber, metadata });
    if (result.isSmsVerificationRequired) setShowVerifySmsForm(true);
  } finally {
    setLoading(false);
  }
};

const onVerifySmsFormSubmit = async (verificationToken: string) => {
  try {
    setLoading(true);
    await client.auth.verifyUserUpdateOtp(verificationToken);
  } finally {
    setLoading(false);
    setShowVerifySmsForm(false);
  }
};

// Resend if needed
const resendSmsOtp = async () => {
  await client.auth.sms.resendOTP();
};

Updating Meta

React Native
import { client } from './dynamicClient';

const onSubmitMetadataOnly = async (metadata: Record<string, any>) => {
  // Updating only metadata typically does not require OTP
  await client.auth.updateUser({ metadata });
};

Updating General

React Native
import { client } from './dynamicClient';

const onSubmitGeneral = async (fields: { firstName?: string; lastName?: string; username?: string }) => {
  // General fields (no email/phone change) typically do not require OTP
  await client.auth.updateUser(fields);
};
Alternatively, you can use the Dynamic UI modal for a simpler integration:
React Native
import { client } from './dynamicClient';

const showUpdateUserModal = async () => {
  try {
    const updatedFields = await client.ui.updateUser.show({
      fields: ['firstName', 'email', 'metadata'],
    });
    console.log('User updated:', updatedFields);
  } catch (error) {
    console.error('User cancelled or error occurred:', error);
  }
};

Socials

Show users linked social accounts, allow linking/unlinking

How: useSocialAccounts hook from sdk-react-core Hook/Component: useSocialAccounts Notes: None

Working with User Metadata

User metadata provides a powerful way to store additional information beyond the standard profile fields. This is perfect for storing user preferences, application state, custom attributes, and integration data.

What is Metadata?

Metadata is a flexible key-value storage system that allows you to:
  • Store user preferences (theme, language, notification settings)
  • Track application state (onboarding progress, feature flags)
  • Store business-specific data (subscription tiers, referral codes)
  • Maintain integration data (external service IDs, webhook configs)

Metadata Examples

// User preferences
metadata: {
  theme: 'dark',
  language: 'en',
  notifications_enabled: true
}

// Application state
metadata: {
  onboarding_completed: true,
  feature_flags: ['beta_features', 'advanced_analytics']
}

// Business data
metadata: {
  subscription_tier: 'premium',
  referral_code: 'USER123',
  last_purchase_date: '2024-01-15'
}

Best Practices

  • Size limit: Metadata is limited to 2KB total
  • Key naming: Use descriptive, lowercase keys with underscores
  • Value types: Supports strings, numbers, booleans, and nested objects
  • Validation: Always validate on your backend before storing
For how to add metadata to the user and update it, see Custom Information Capture.
  • Updated the “Allow user to update their profile information” section with distinct “Updating Email”, “Updating Phone”, “Updating Meta”, and “Updating General” subsections for both React and React Native, and used isSmsVerificationRequired for phone updates.