User Profiles
Users, profile fields and sign-in: account forms and pages, plus sign-in with Google, GitHub, Apple or Discord.
User Profiles is where your users live. It lists everyone on the site, decides what their profiles ask for, and runs how they sign up and sign in: your own sign-up, sign-in and password pages, built from forms, plus sign-in with Google, GitHub, Apple or Discord. It also shows your users in a directory, lets each user choose who sees their answers (privacy), and lets you suspend an account.
It is built on Forms. Every profile question is a Forms field, and every sign-in page holds a form. Everything underneath is WordPress's own account system: signing in sets the normal session cookie, a sign-up makes a normal user, and a password reset uses WordPress's emailed link.
User Auth and Social Login used to be separate plugins. They are part of User Profiles now; see Moving from User Auth and Social Login.
Forms has to be active
Without XPAC Forms there is no User Profiles screen, no profile fields and no sign-in forms, just an admin notice asking for Forms. Social Login's buttons outside forms still sign in linked accounts, and its settings keep their own page in the XPAC menu.
Where to find it
Open XPAC → User Profiles. The sidebar has three groups. Users holds User Profiles, a list of everyone with a page per user, and Profile fields, the questions profiles ask. Login holds Forms and pages, the form and page for each sign-in task. Social Login holds Providers, the providers and their keys, and Sign-up data, what a provider sign-up fills in.
Users
User Profiles opens first. It is the same kind of list table WordPress uses on its newer screens: everyone on the site, newest first, 20 to a page, with a line at the top counting them all. At first it shows:
- Name: the user's picture and name. Click either to open their page.
- Email: their email address.
- Role: their WordPress role.
- Status: every user has an email status. Email confirmed once they confirmed their email, Waiting for confirmation while they still have to, and Not confirmed when they were never asked to, such as an account an admin made, an imported one, or one made before email verification was on. Someone who confirmed stays Email confirmed after you switch verification off. A suspended user also shows Suspended, and statuses other plugins add show next to it.
- Registered: the day the account was made.
Every profile field that keeps an answer is a column too, hidden until you show it. The Email Address field is the Email column, so it is not listed twice. Checkbox and dropdown answers show as the words people picked, not their stored values.
Search, filter and sort
Type in the search box to find users by name, username or email. Click Add filter to narrow the list by a column, then pick how to match and what to match:
- Text, email, URL and phone fields: Contains, Doesn't contain, Is, Is not or Starts with.
- Number fields: Is, Is not, Less than, Greater than, Less than or equal, Greater than or equal or Between (inc).
- Date fields: On, Not on, Before, After, Before (inc), After (inc) or Between (inc). Registered can also be In the past or Over a number of days, weeks, months or years, by your site's calendar.
- Role, and dropdown and radio fields: Includes any of the choices you tick, or Is none of them. Checkbox fields can also be Includes all.
- Status: Is or Is not one status: Email confirmed, Waiting for confirmation, Not confirmed, or one another plugin adds.
Each filter shows as a chip in the bar; click it to change it, or its × to remove it. People must match every filter. A filter that says not also matches the people who left that field empty. Click a column's heading to sort by it; people who left a field empty come last.
Choose the columns
Open View options (the cog) to choose which columns show and in what order, how many rows a page holds (10, 20, 50 or 100) and how roomy the rows are (Density). It also sorts. Your choice is kept for your account, so it is there the next time you open the list; other admins keep their own. Reset view goes back to the columns, rows and sort the list starts with.
Search, filters, sort and page stay in the address, so the browser's Back button and a link you share open the same list.
Export CSV
Click Export CSV to download what the list shows now: the users your search and filters
find, in its sort order, with the columns you show, in their order. The button counts up while it
works (Exporting… 40%), then your browser saves a file named like users-2026-10-06.csv.
The first column is always the name. Every cell says what the list shows: roles and statuses in
words, the registration date and time by your site's clock, and checkbox and dropdown answers as
the choices' labels. Text that starts with =, +, - or @ gets a leading ' so a spreadsheet
shows it instead of running it as a formula.
Remove a photo
When a user has uploaded a photo, the row's actions menu (⋮) has Remove photo. Confirm, and the photo is gone; the user can upload a new one.
A person's page
Click a user's name to open their page. At the top are their name, email, role, any status badges and sign-up date, and Open in WordPress, which opens their usual WordPress profile.
Below, each field set has a card with the person's answers, one box per field, ready to change. Change what you need and click Save changes. Leave a box empty to clear that answer; as an admin you can leave even a required field empty. If an answer cannot be saved, such as an email address another account already uses, the page says why and marks the field, and nothing is changed. The page warns you before you leave with unsaved changes, and ← User Profiles takes you back to the list where you left it.
- The Account fields are the person's WordPress account: changing the first name, last name, nickname or email here changes the account itself. WordPress emails the old address when the email address changes, as it does in the WordPress profile. The Password field is never shown.
- Some fields, such as an avatar upload, are shown but cannot be changed here. The avatar shows the photo the person uploaded, or No photo yet. With a photo, Remove photo appears next to it: confirm, and the photo is gone. The person can upload a new one.
On the right, Sign-in methods lists how the person signs in: with a password, and with each provider linked through Social Login. Details shows when they joined, the provider they signed up with, their role, whether their email is confirmed, how much of their profile is filled in, and their user ID.
Profile fields
Each question a profile asks is a field, such as a company, a job title or a phone number. Fields are grouped into field sets, such as Account and Work, so a long profile stays easy to read and to manage. Users fill fields in through your sign-up and profile forms, and their answers are saved to their account.
Field sets and fields
Profile fields shows one card per field set, in order. Each card lists its fields with their Type, their Key and how many forms use them (Used in). Above the cards, a line counts your field sets and fields.
- A field set has a name and an optional description. It only groups fields on this screen; it does not change what users see.
- A field has a label, a type, a key and a field set, plus optional help text, a placeholder, choices and a Required rule.
The types are Text, Textarea, Email, URL, Phone, Number, Date, Time, Dropdown, Radio buttons and Checkboxes.
Add a field
Click Add field at the top of the page, or Add field to … at the bottom of a set's card to put it straight into that set.
Under Basics, type the Label and pick the Type. The Key fills in from the label as you type; change it if you want a different one, before you save.
Add Help text and a Placeholder if they help. For Dropdown, Radio buttons and Checkboxes, list the Choices: each has a label and an optional value, and you can drag them into order.
A new field shows to users only once a form holds it. Until then Used in says Not used in any form yet.
Edit a field
Click a field's row to open it. Change what you need and click Save field; Cancel goes back without saving, and the page warns you before you leave with unsaved changes.
The right-hand side shows the forms that use the field, each with a link to edit it, and how many users have saved an answer. A change to a field shows in every form that holds it.
What is locked, and why
- The key never changes once the field is saved. Every user's answer, and every form that holds the field, finds it by its key. Pick it with care: lowercase letters, digits, hyphens and underscores, starting with a letter, up to 64 characters. A key another field uses, even one in the trash, is taken, and so is a key that answers from a deleted field are still saved under.
- The type is locked once users have saved answers, so their answers keep making sense. Before that you can change it, and the label, help text and rules come along.
- Some fields are edited in the block editor. A field of a type this screen does not offer, such as an avatar upload, shows its own type and a note with an Open in the block editor link. Here you can change only its label and field set.
Built-in fields
Five fields belong to every account: the first name, last name, nickname, email address and
password, with the keys firstname, lastname, nickname, user-email and password. They sit
in the Account set, marked Built in.
You can change their label, help text, placeholder and Required rule, and reorder them inside Account. You cannot delete them, change their key or type, or move them out of Account, and the Account set itself cannot be deleted. These keys are reserved, so no new field can take them.
If one of the first four is missing, unpublished or in the trash, User Profiles puts it back in Account the first time it runs, so every site has them. The Password field is added once, at the end of Account.
The Password field
The Password field is the fifth built-in field. It holds Forms' Password field, so a form that needs a password, such as a sign-up or sign-in form, uses it like any other profile field. On the Profile fields page its row says Never stored.
- The password is never kept as an answer. It goes to the WordPress account and nowhere else: not into answers, submissions, notification emails, exports, columns, integrations or Sign-up data, and it is never filled in for anyone.
- Its rules. Open the field to set Password strength (a meter that refuses weak passwords), Minimum strength and Show password toggle (the eye icon that shows what was typed). The levels are Insecure (4 or more characters), Bad (8 or more), Good (upper and lower case, 8 or more) and Strong (upper and lower case, a number and a symbol, 8 or more). It starts with the strength check on at Good, the toggle on, and not required.
- What you can change. Its label, help text, Required rule and the three rules above. Its key, type and set are locked, and it counts for nothing in profile completion.
- Sign-in forms skip the strength check. A login form only checks the password someone already has. Sign-up, reset and profile forms check it.
- Confirm password. Pair it with a Confirmation field, the way Forms confirms an email address. The forms User Profiles makes for you already do.
If another field already uses the key password, no Password field is added and an admin notice
says so.
Reorder
Drag a field set by its handle to move it up or down. Drag a field to move it inside its set, or into another set. The new order saves as soon as you drop; if it cannot be saved, the page puts things back and says so. Built-in fields stay in Account.
With a keyboard, focus a handle, press Space or Enter to pick it up, move it with the arrow keys and press Space or Enter again to drop it. Escape puts it back.
Field sets
- Add field set opens a box for a Name and an optional Description. A new set goes at the end, and no two sets can share a name.
- Edit set on a card renames it or changes its description.
- The trash button, Delete set, shows only on an empty set that is not built in. Move or delete its fields first.
When you first update, the fields you already have are sorted for you: the built-in fields go into Account, and every other field into a Profile set, in the order they had.
Delete a field
Open the field and click Delete field. The confirmation lists the forms that use it and how many users have answered it. Deleting moves the field to the trash, and those forms stop showing it. Their answers stay saved: nothing is removed from your users' accounts.
Links from the block editor
Profile fields used to be edited one at a time in the block editor. The old Add field and edit links for profile fields now open this screen instead: a new field opens New field, and an existing field opens its own page. Fields this screen does not edit, such as an avatar upload, still open in the block editor.
Profile fields in your forms
A profile field on a form works like the Forms field it holds. Your integrations and notification emails get its answer the way they get that field's: a choice as its label, a phone number in the field's format, a file as a link or an attachment.
A form with profile fields and no sign-in task saves them to the signed-in user's own profile. An email change waits until the new address is confirmed, and a new password needs the current one. Signed-out visitors' answers are only a submission.
Blocks for profiles
| Block | Name | What it shows |
|---|---|---|
| Profile field | xp/profile-field | One profile field inside a form, filled with the user's answer. |
| Avatar Upload | xp/avatar-upload-field | A photo upload inside a form. A user can drop a photo on it. |
| User Profile Data | xp/profile-data | One person's answer to a field, as a paragraph. |
| User Profile Dropdown | xp/account-menu | The signed-in user's photo, opening View profile, Settings and Log Out. |
| Profile Dropdown | xp/profile-dropdown | The signed-in user's menu, built from blocks you can change. |
| User Avatar | xp/member-avatar | A user's photo. |
| Display Name | xp/member-name | A user's display name. |
| Profile Completion Banner | xp/profile-completion-banner | A message for users whose profile is not complete enough yet. |
| Profile Completion Tracker | xp/profile-completion-tracker | How complete the user's profile is, as a row of steps. |
| Users Query | xp/users-query | Users in a grid or a slider. See Directory. |
| Users Query Total | xp/users-query-total | How many users match a filter. |
| Privacy Preference | xp/privacy-setting | Lets the signed-in user pick who sees one part of their profile. See Privacy. |
- Whose profile. User Avatar, Display Name and User Profile Data show the user a page is about: the template's person, a comment's author, or a user's profile page. Elsewhere they show the signed-in user. Their name and photo update as soon as that user saves their profile.
- The account menu. Its profile link goes to the user's profile page, when the site has one, and Settings to the account page the site had set. Under the name it shows the profile fields you pick in Details (a job title and an employer by default, read "Designer at Acme"), and nothing while they are empty.
- Profile Dropdown. The newer menu, made of ordinary blocks. Its Dropdown Toggle is the button: the user's photo and an arrow, or pick Avatar and name in the inserter. Its Dropdown Panel opens under it and holds any blocks: by default the user's photo, name and email, a Navigation block with Profile and Account links to those pages when your site has them, then Login/out. Edit the menu like any other, restyle both parts like any block, and set where the panel sits from its toolbar; left unset, it opens toward the side with room. Visitors who are not signed in see nothing. Select an old User Profile Dropdown and choose Transform to → Profile Dropdown to move to it; the old block keeps working.
- Profile completion. Each published field weighs its Field weight (1 when unset, 0 leaves
it out), and a user's completion is the share of that weight they filled. It is worked out
again on every save, at sign-in, and in the background after you change a field's weight or
publish or remove a field. The banner shows below its Completion Threshold and comes back
after its Reappearance Interval once dismissed.
{{ProfileCompletionPercentage}}in any paragraph prints the number. {{key}}in text. A paragraph that holds{{job-title}}shows the user's own answer.- Show a group to some visitors. Select a Group block and open Visibility Options. User permission shows it to Guests only, Signed-in only, or the Profile owner on their own profile page. With Everyone, Profile Field Relations shows it only to signed-in users whose answers match, such as Show if all of the following options match: Country is France. On a user's profile page, that user's answers are used. Privacy Relations, in the same panel, shows it only to visitors the user's privacy choices allow.
Login forms
Your site's own sign-up, sign-in and password pages are forms on pages. Login → Forms and pages lists each task with the form that does it and the page that shows it. Below the list, one Settings card holds the rest of sign-in and access.
| Used for | What it does | Its page |
|---|---|---|
| Registration | Creates accounts. | Your sign-up page. |
| Login | Signs users in. | Your sign-in page. WordPress's Log in links open it. |
| Forgot password | Sends a reset link. | Where Lost your password? goes. |
| Reset password | Sets a new password. | Where the emailed reset link lands. |
| Update password | Changes the password of a signed-in user. | None. Put the form on your account page. |
| Account verification | Resends the verification link. | Where the emailed verification link lands. |
Each row shows its Form, by title and #id, linked to the form's editor, and its Page, by title and address, linked to the page. Rows only show what is set; you change one through its actions:
- Edit form opens the form in the editor.
- View page opens the page.
- Change… opens a small window with Form and Page. Its Save saves that row alone.
- Create, on a row with no form, makes a minimal form and a published page. See What Create builds.
The Update password row has a form and no page: Change… and Create deal with the form only.
A row shows a warning under it only when something is wrong, such as Form is not published., Page does not show this form., Page was deleted., Page is not published., Form has more than one sign-in action., Add the Email Address field to this form. or Registration is closed in Settings › General. While email verification is off, the Account verification row says Not used while email verification is off.
Set up a row
On a row with no form, choose Create to have User Profiles make a minimal form and a published page for it. To use a form you already have, choose Change… and pick the Form and the Page that shows it.
Saving checks the row first and writes nothing when it is refused. The form you pick starts doing that task, the form that did it before stops, and a page that showed the old form is pointed at the new one. A page can serve only one task.
What Create builds
- Registration: Email Address and Password (both required), Confirm password, First Name and Last Name. Page Create account.
- Login: Email Address, labelled Username or email, and Password. Users sign in with
either one, as on
wp-login.php. Page Sign in. - Forgot password: Email Address. Page Forgot password, button Send reset link.
- Reset password: Password and Confirm password. Page Reset password, button Set new password.
- Account verification: Email Address. Page Verify your email, button Send a new link.
- Update password: Current password, Password labelled New password, and Confirm password, button Update password. No page: put the form on your account page.
Every field is a profile field, so the form fills the account from them with no setup. When a Social Login provider is set up, the Registration and Login forms also get a Social Login block with a button per provider. When a page for the task already exists but shows no working form, Create reuses it.
Current password is a field block for forms that change a password. Only a signed-in user who has a password sees it; a user who signed up with a provider sets a password without it.
The Settings card
Below the list, the Settings card has its own Save and three groups.
Registration
- Require email verification for new accounts. See Email verification.
- Role: the role new users get. Site default (Subscriber) follows Settings → General → New User Default Role. Only roles you may give, and none with admin powers, are offered.
- Log in after registration: signs new users in at once. Skipped when email verification is on.
Role and Log in after registration apply to the chosen Registration form. Without one they say Set up a registration form first. A form whose sign-up items give different roles or log in differently keeps its own: they say This form sets these by its own rules. and cannot be changed.
Pages
- Public Profiles: lets signed-out visitors see profiles.
- Profile page: Shows a user's profile to others. See Profile page.
Access
- Signed-in only pages and Signed-in only post types. See Signed-in only pages.
- Require account verification for signed-in only pages.
- Onboarding pages, kept in the order you pick them, and Mandatory onboarding: Restrict access to signed-in only pages until onboarding is complete. See Onboarding.
- Keep users out of wp-admin. See Keep users out of wp-admin.
- After confirming email, go to: a path such as
/welcome, or an address on this site. Empty shows the default message.
The Access settings used to be under Community → Settings → Pages. They moved here with their saved values, and Community's Pages tab no longer shows them.
Made for you on a fresh site
Activating User Profiles on a fresh site makes all six forms and five pages the first time someone who
can set up sign-in and publish pages opens wp-admin. A site counts as fresh when it has no other
user, no form, no Social Login settings and nothing from User Profiles or User Auth before. Nothing
is made when a sign-in page is already set, a form already does a sign-in task, a page already uses
one of the slugs create-account, sign-in, forgot-password, reset-password or
verify-your-email, or a developer says no. If making them fails, nothing is kept and the screen
says why.
In Forms → All Forms
A form that does a sign-in task shows a badge after its #id, such as Registration. Its tooltip reads Registration form · User Profiles › Forms and pages, and clicking it opens Login → Forms and pages.
Forms made before
Forms set up with the old User Auth panel keep working exactly as they did, with their account mapping and settings. The form editor no longer has that panel or a User Auth choice under Add action: a form's sign-in task is chosen on Login → Forms and pages, which keeps the form's saved settings.
- Several forms for one task. The row shows the one in use, picked on the screen, then the one on the task's page, then a published one, then the lowest ID. The rest are listed as Also: links to their editors and keep running. The AI agent can switch one off.
- Profile fields fill the account. On a form whose sign-in task maps nothing, the Email Address, First Name, Last Name, Nickname and Password profile fields fill the account. On a mapped sign-up or profile form, those profile fields replace the mapped field, and other profile fields fill only what no mapped field gives.
- Current password. On a profile form, the current password comes from the Current password block. A signed-in password change without it is refused.
What a form can do
| Task | What submitting does | Visitor must be |
|---|---|---|
| Registration | Creates an account from the answers | Signed out |
| Login | Signs the visitor in | Signed out |
| Update (a profile form) | Saves changes to the signed-in user's account | Signed in |
| Forgot password | Emails the standard WordPress reset link | Either |
| Reset password | Sets the new password after that link is followed | Signed out |
| Update password | Changes the signed-in user's password after checking the current one | Signed in |
| Account verification | Sends the verification email again | Either |
One submission runs at most one task. A form that would run several at once is refused before any account changes.
Mismatches are handled for you: a login or registration form shown to someone already signed in is replaced with "You are already logged in.", and a profile form shown to someone signed out with "You need to log in or register." Its log in link brings them back to the page after they log in, and opens your login page; its register link opens your registration page the same way. While Settings → General → Anyone can register is off, the message is only "You need to log in."
A visitor who logs in goes back to the page a Log in link named, when it is on your site, else
to the form's own redirect, else to the home page. A
login form takes the account's own password only: an application password, which WordPress keeps
for apps and the REST API, is refused, as it is on wp-login.php.
Log in and Register links
Once your Login page is set and published, WordPress's own Log in links on your site open it instead of the WordPress login screen: the Log in/out block, including one in a menu, the comment form's log-in links, and the links on the WordPress login screen itself. A link that names the page the visitor was on brings them back to it after logging in. Register links open your Registration page the same way.
- Logging out ends on your login page when the Log Out link names no page to return to, as the one in the toolbar does.
- wp-admin keeps the WordPress login screen. Links inside the dashboard, and the screen that asks a signed-in user for their password again, still use it.
- A page that is not set or not published changes nothing. A draft, a page in the trash, or no page at all leaves WordPress's own links as they were.
- Signed-in visitors skip them. A signed-in user who opens the login or registration page is sent to their profile page, or where the login form's redirect goes when there is no profile page, or the home page when there is neither.
Role safety
Five rules keep a form from handing out more power than you meant:
- A form keeps only roles its saver may give. When someone saves a form with a role they could not give themselves, whether in the editor, through the REST API or through the AI agent, the role is removed before the form is stored, and the site's PHP error log says so. A role the form already had stays when they save other changes.
- Sign-ups never get admin powers. A registration form never gives the Administrator or Editor
role, or any role with powers like theirs (managing users, plugins, themes or site settings, or
posting unfiltered HTML), even when an administrator picked it. The new account gets New User
Default Role instead, and the PHP error log says so. A developer can change which powers count
with
xpac_user_auth_agent_role_ceiling. - A profile form never gives or takes admin powers. A role on a profile form is not applied to a user who has such powers, and a role with such powers is never given to anyone who saves the form; the PHP error log says so. Their other changes still save. Any other role on a profile form goes to every user who saves it.
- No form writes the account's own records. A user meta name that WordPress or a plugin keeps
for itself, such as the account's capabilities, anything starting with an underscore or the
database table prefix, an account detail, or a name with spaces around it or letters outside
plain ASCII, is removed when the form is saved and left out when someone submits it. A developer
can let forms write one of the named keys, such as
locale, with thexpac_user_auth_agent_reserved_metafilter. - The AI agent never gives such a role at all, not on a form and not as the default role, and never puts a role on a profile form. See Build it with the AI agent.
Registration respects Settings → General → Anyone can register. With it off, the form answers
Registration is not open on this site. The xpac_forms_user_auth_allow_registration filter can
override that for an invite-only flow.
Password resets
Forgot-password and reset-password forms drive WordPress's own reset, so the link's security is WordPress's: emailed only to the address on the account, dead after a day, dead once used. Once the Reset password row is set up with no warning, the link in the reset email opens your page instead of the WordPress login screen. Request a reset and check.
The same page takes the link in the email WordPress sends each new account a registration form creates, the one for setting a password. Both emails link to the page's own address, so it can sit anywhere on your site, a child page included.
Email verification
Turn on Require email verification for new accounts in the Settings card's Registration group, and every account a registration form makes gets a link it must open. Opening it shows a confirmation step: the visitor presses Verify email address before the token is used, so mail scanners and link previews that open links do nothing. The confirmation is nonce-protected and safe to repeat.
- Unconfirmed accounts cannot sign in, on your login form or on
wp-login.php, and are not signed in after registering. The link lasts two days, changeable withxpac_forms_user_auth_token_lifetime. - The page needs its form. The link opens the Account verification page, and the confirmation appears only on a form there that resends verification. The row shows no warning when it does.
- A failed email is retried. If mail delivery fails after the account is made, the form says the request was accepted but the email was not sent. Sending the same registration again, or the Account verification form, retries the email instead of making a second account.
- Provider sign-ups. A sign-up through a provider gets the same email unless Skip email verification for social sign-ups is on; see Email verification and signing in.
Before you launch
Limit attempts in front of the site
Forms allows each visitor 20 attempts per form in five minutes by default, set under XPAC → Forms → Settings → Spam and abuse. Nothing else counts failures: no account is locked, and nobody is asked for a code after wrong passwords. Insist on strong passwords with the Password field's rules, add an anti-spam add-on to the sign-in forms (reCAPTCHA, Turnstile or Akismet), and put a rate-limiting service in front of a site that holds anything valuable.
Outbound mail still needs monitoring
User Profiles cannot make your host deliver mail. Test the registration, verification, email-change and password-reset messages before launch, and watch your mail transport in production.
- Answers are generic. Login, registration, forgot-password and verification forms do not say
whether an account exists. Turn on specific messages with
xpac_forms_user_auth_reveal_accounts; then a taken address at registration answers "You already have an account. Sign in instead." with a link to your login page. - Passwords are write-only. Password and current-password answers are removed before submissions, notifications, integrations, exports or hooks can see them, and so are copies of the same value in other fields.
- Redirects stay on this site. A target on another site falls back to the form's redirect or the home page.
- Check the pages in a private window. Signed in, the login and registration pages send you to the account page, and the reset page shows Not Found to anyone who did not open it from a reset email's link.
Account area
These used to be part of Community Platform. They work on any site with User Profiles.
Account page
There is no Account page setting. For a users' own page:
- Add it to Signed-in only pages to keep signed-out visitors out.
- Give your login form a Redirect to it, so users land there after signing in.
A site that had an Account page set keeps both: the upgrade adds the page to Signed-in only pages
and gives each login form without a redirect one to it. The account menu's Settings link, the
Profile Dropdown's Account link and the {accountUrl} email tag still open that page.
Profile page
Profile page, in the same group, is one page that shows any user, named after it by their
username slug. If the page is /profile/, then /profile/jane/ shows
Jane, and blocks that show a person, such as User Avatar, Display Name and User Profile Data, show
her.
- A signed-in user who opens the page itself goes to their own profile. An address that names nobody is page not found.
- Public Profiles, the switch above it, lets signed-out visitors see profiles. It is on until you turn it off. While it is off, signed-out visitors go to your login page and come back after signing in.
- The account menu's View profile link opens the user's own profile, and Users → All Users gets a View link on each user.
- Signed-in users who open the login or registration page go to their own profile.
It used to be Community Platform's Profile page and Public Profiles under Community → Settings → Pages. The upgrade copies both into User Profiles, and old profile addresses keep working.
Signed-in only pages
Pages, and post types, that only signed-in users may open. They were called Member-only pages before. Pick them in the Settings card's Access group, as Signed-in only pages and Signed-in only post types, which lists your public post types except pages and media. A signed-in only page covers the pages under it too, and a signed-in only post type covers its single posts, archives and terms.
- Signed-out visitors go to your login page and come back after signing in.
- With Require account verification for signed-in only pages on, users who have not confirmed their email go to the Account verification page.
- Administrators always get in.
- Visitors who would be sent away also get nothing of a signed-in only page, the pages under it, or a signed-in only post type from the REST API, feeds, the site search or embeds, and the sitemaps leave them out. Sign-in pages always stay open, and the upgrade takes any that Community listed out of Signed-in only pages and Onboarding pages. Query Loop blocks and widgets still list signed-in only posts, so keep those off public pages. Users who can edit posts always see them.
- A post type that is no longer registered stays in the list under its name until you remove it.
Onboarding
Onboarding pages and Mandatory onboarding, also in the Access group. The pages keep the
order you pick them in. While Mandatory onboarding is on, a user who has not finished onboarding is sent to the first
onboarding page instead of a signed-in only page. A user has finished once the
user meta xpac_user_profiles_onboarded is set; Community's older onboarding_complete counts too.
Administrators are never sent.
Keep users out of wp-admin
With Keep users out of wp-admin on, users (subscribers) who open wp-admin go to the home
page and see no admin bar. Requests the site makes in the background still pass, and so do
Social Login's sign-in callbacks and Support's authors. It is off until you switch it on; Community
Platform switches it on once, the first time it runs, when the setting has no value yet. A developer
can let single requests through with the xpac_user_profiles_allow_admin_access filter.
After confirming an email
Set After confirming email, go to in the Access group to a path such as /welcome, or an
address on this site, and users who confirm their email go there. Left empty, they see the
account activated message. Community Platform sets it to /dashboard once, the first time it runs,
where that page is published and the setting has no value yet.
A sign-in page can't be signed-in only, sit below a signed-in only page, or be an onboarding page: signed-out visitors could not reach it. The screen says which page and keeps Save off.
Where the settings live
| Setting | Where it is now |
|---|---|
| Login, registration, forgot password, reset password and account verification pages | Login → Forms and pages, one row each |
| Require email verification for new accounts, new users' role, log in after registration | Login → Forms and pages, Settings, Registration |
| Public Profiles, Profile page, Search page | Login → Forms and pages, Settings, Pages |
| Signed-in only pages and post types, verification for them, onboarding, keeping users out of wp-admin, where to go after confirming an email | Login → Forms and pages, Settings, Access |
| Provider keys, buttons on the WordPress login page | Social Login → Providers |
| What a provider sign-up fills | Social Login → Sign-up data |
Forms → Settings no longer has a User Auth page, and its old links open Login → Forms and pages. The old Social Login settings page opens Social Login → Providers.
Directory
Show your users on any page with the Users Query block. It works with or without Community Platform.
- Layout: a slider or a grid, with how many columns and rows, and an optional Load more button under the grid.
- Each card shows the user's photo and name, both linking to their profile page, and one profile field under the name. Pick that field in Card line (Job Title by default, or None).
- Query: order by name, email, ID or registered date; leave out the current user; and Filter by what other plugins add, such as a user's connections from Community Platform.
- Filter by search keyword shows only users matching the search on the current page.
- No-results text is what shows when nobody matches ("No users to display yet." by default).
Users Query Total prints how many users match the same filter, for a heading such as "128 users".
Search page
Pick a Search page in the Settings card's Pages group on Login → Forms and pages. It is optional and shows as off until you pick one. With it set, the Autocomplete Search block sends its searches there, ends its suggestions with a See more results button when its See all results setting is on, and lists users with their names linking to their profiles. With no page picked, nothing about search changes.
Leave someone out
Administrators start out left out of the directory and the search results. To list one, open their
profile in Users → All Users and tick Include in user search. On WordPress VIP the
wpcomvip account is always left out.
Privacy
Users choose who sees each profile answer, and other parts of their profile, with the Privacy Preference block. Put one block on the account page for each answer you want users to control and pick it in Privacy preference.
| Choice | Who sees it |
|---|---|
| Everyone | Anyone, signed in or not. |
| Only me and admins | The user and site administrators. |
| My Connections | The user, administrators and the user's connections. Added by Community Platform. |
The choice applies everywhere the answer prints: the User Profile Data block, the line under the name in the account menu, and any Group block with Privacy Relations. A save that fails shows an error, and the choice goes back.
Suspension
To suspend an account, open the user in Users → All Users, tick Suspend and save. A suspended user:
- is signed out at once and cannot sign in, with "Your account has been suspended. Please contact the site administrator for assistance.";
- gets the same refusal from the REST API;
- shows Suspended in Users, where you can filter by it.
You cannot suspend your own account. Untick Suspend to let them back in. Suspended users still show in the directory and the search results. The AI agent can suspend a user too, after you allow it in the chat.
User notices
With the XPAC: Notifications plugin active, User Profiles sends three notices. Switch each one's On-site and Email channels on the Notifications screen in wp-admin, under Users, and users can turn them off with a Notification Preference block.
- Welcome, on sign-up. When the user chose their own password and the welcome email went out, WordPress's own new-account email is not sent for that sign-up.
- Password reset, on-site only.
- Profile incomplete, a daily reminder to users whose profile is less than 80% complete. The first one goes out a day after XPAC: Notifications is turned on.
Without XPAC: Notifications, none of these are sent, and WordPress sends its own new-account email.
Social Login
Social Login adds Sign in with Google, GitHub, Apple and Discord buttons to your site. A visitor whose provider account is linked to an account here signs straight in. Signed-in users can link more providers to their account, or unlink them, from an account page.
New accounts come only from a sign-up form: the buttons inside a Registration form fill the form from the visitor's provider account and send it for them (see Sign up through a form). Which profile field each piece of sign-in data fills is set on Sign-up data.
General
Social Login → Providers opens with a General card:
- Show buttons on the WordPress login page adds the buttons below the form on
wp-login.php, after an "or" divider, one for every provider that is enabled and set up. It starts off. - Skip email verification for social sign-ups shows while new accounts must confirm their email. The provider already verified the address. Applies to sign-ups through a form.
Below it is one card per provider, marked Set up or Not set up. Click Set up or Edit to open it, and Save at the top when you are done. Only one card is open at a time.
Set up a provider
Each provider card starts with its setup steps and a link to the provider's own guide, then a Callback URL. It looks like this, with your own domain and the provider's name at the end:
https://example.com/wp-admin/admin-post.php?action=xpac_oauth_callback&provider=googleCopy it exactly as shown, including the part after ?, into the provider's console. Then paste the
provider's keys into the card, turn on Enable for that provider, and save. A provider's buttons
appear only while it is enabled and its keys are complete.
Saved keys show in their fields like any other setting. To replace one, paste the new value and
save. If the site moves to another domain, switches between http and https, or WordPress moves
to a different folder, the callback URLs change: copy them again and update each provider's
console.
- Open the Google card and copy the Callback URL.
- In Google Cloud, set up the consent screen and create an OAuth client of type Web application.
- Add the callback URL under Authorized redirect URIs.
- Paste the Client ID and Client secret, turn on Enable Google and save.
See Google's setup guide. While your Google app is in testing, only the test users you list there can sign in. Google's extra permissions need Google to verify your app first.
GitHub
- Open the GitHub card and copy the Callback URL.
- In GitHub, open Settings → Developer settings → OAuth Apps and register a new app. Use your site as its homepage and the callback URL as its Authorization callback URL.
- Generate a client secret, paste it and the Client ID, turn on Enable GitHub and save.
See GitHub's setup guide. Only GitHub.com is supported. Sign-in uses the account's verified primary email address.
Apple
Apple accepts only an https callback on a real domain name, so this provider needs HTTPS. The card
says Apple needs a site on HTTPS. when the site is not.
- Open the Apple card and copy the Callback URL.
- In your Apple Developer account, turn on Sign in with Apple for a primary App ID, create a Services ID for your website and link it to that App ID.
- On the Services ID, add your website's domain and the callback URL as a Return URL.
- Create a Sign in with Apple key and download its
.p8file. Note its Key ID and your membership's Team ID. - Enter the Services ID, Team ID and Key ID. Open the
.p8file in a text editor, copy all of it and paste it into Private key (.p8). Turn on Enable Apple and save.
User Profiles signs the short-lived secret Apple asks for from that key on every sign-in, so there is nothing to renew. See Apple's web setup guide and key guide.
People can hide their address with Apple's Hide My Email. For WordPress emails to reach those relay addresses, register your sending domain with Apple's private email relay service.
Discord
- Open the Discord card and copy the Callback URL.
- Create an application in the Discord Developer Portal and open its OAuth2 page.
- Add the callback URL under Redirects.
- Paste the Client ID and Client secret from that page, turn on Enable Discord and save. The client secret is not the bot token.
Sign-in asks Discord only for the account's name and email address, unless you switch on its Linked accounts extra permission. It does not add a bot or join any server.
The two blocks
Social Login block
Add the Social Login block to your sign-in pages. Visitors see its buttons; someone already signed in sees nothing.
- Layouts. Pick one when you insert the block, or switch later from the block toolbar or the sidebar's Transform to variation: Social Login (full-width buttons in a column), Row (side by side, wrapping on narrow screens), Icons (round logo-only buttons) or Compact (small pill-shaped buttons). Switching keeps the buttons and the look. Row sets the size back to medium and Compact to small; Icons and Compact also set a fully rounded corner.
- Looks. Under Styles, pick Theme (your theme's button colours), Brand colours (each provider in its own colours) or Outline. A new block starts with Brand colours.
- Buttons. Each provider is a button inside the block, and a new block starts with one for every provider. Add another with the block's + button, and move or remove one like any other block. A provider that is not set up yet is greyed out in the editor with a warning, and hidden on the site until it is. A provider added twice shows once.
- Button text is typed on the button itself. Leave it empty for the default, Sign in with Google and so on, or Sign up with Google inside a sign-up form. Google and Apple ask that their buttons say Sign in with, Sign up with or Continue with.
- Settings, in the block's sidebar: Show text (on by default; off keeps the text for screen
readers and as a tooltip), Size (Small, Medium or Large) and Icon position
(Start, Edge or End). Redirect after sign-in (under the panel's ⋮ menu) is an
optional page on this site. Empty uses the usual destination, and a page opened with
?redirect_to=passes that on.
The block's toolbar aligns the buttons and switches between a row and a column; its Layout settings set the gap, wrapping and vertical alignment. Its colour, typography, padding, border and shadow settings style every button at once, and each button can then override its own.
Connected Accounts
Add the Connected Accounts block to your account page. Visitors who are not signed in see nothing. A signed-in user sees each provider that is set up, marked Linked or Not linked, with a Link or Unlink button. A provider an administrator has since turned off stays listed while it is linked, so it can still be unlinked.
After linking, go to is an optional page on this site; empty comes back to the same page. Pages that carry the block are never cached. Signed-in users also see the same list under Sign-in methods on their own WordPress profile screen.
Messages
When a sign-in, link or unlink does not work, the visitor comes back to the page where they clicked and the block shows a short message above its buttons, for example that sign-in was cancelled or that the request expired. Linking and unlinking show a confirmation the same way. Keep each block on the page where its buttons are clicked.
When the provider account belongs to nobody on the site, the message reads "No account uses this Google account yet. Create an account first." with a Create an account link to your sign-up page: the Registration page once it is set and published, or WordPress's own sign-up screen while Anyone can register is on. With neither, the message asks the visitor to sign in another way or contact the site administrator.
The WordPress login screen
With Show buttons on the WordPress login page on, the buttons appear on wp-login.php below its
form. Messages show in the login screen's own notice area.
Sign up through a form
Put the Social Login block inside a Registration form and visitors can fill and send that form with their Google, GitHub, Apple or Discord account. The form stays in charge: it makes the account, the submission is saved, and every integration the form is connected to runs, all with the provider's verified email address and the names it gives.
What it needs
- A form that registers people: the Registration form on Login → Forms and pages, or another form with a registration task from before.
- The Email Address profile field in the form, or a mapped email.
- At least one of the block's providers set up and enabled (see Set up a provider).
- The site, its admin and its REST API on one address (the same
https, domain and port).
The forms Create makes already have the block when a provider is set up.
Add the buttons
In the block's sidebar, Field holds the block's Label (Signed up with by default) and its Name, and says what a sign-up fills, with a Choose the fields link to Sign-up data. Settings keeps Show text, Size, Icon position and Redirect after sign-in.
What visitors see
- The visitor fills what the form asks besides the email, names and password, such as a consent box, and clicks a button, such as Sign up with GitHub.
- The form checks those other fields first. If one is wrong, it shows the error in place and nothing else happens.
- A small window for that provider opens; the page stays where it is. The visitor signs in there.
- The window closes itself and the form is sent for the visitor. A line under the buttons says "Signing up with GitHub as [email protected]."
The provider's email, and the data it gives for the fields a sign-up fills, replace what was typed in those fields. The password, its confirmation and a username field are not needed for a provider sign-up: a username is made from the email, and the account starts without a password its owner knows (see Existing accounts). If the visitor types into an email, password or username field after the provider answered, the form goes back to a normal sign-up.
When a field still needs the visitor, such as a required phone number the provider did not send, the form is not sent. It shows only what is left, marks the fields to fix, and the line says "Signing up with GitHub as [email protected]. Check the marked fields, then send the form." A Use a password instead link brings the hidden fields back for a normal sign-up; in a form without a password field it reads Sign up without GitHub.
Other outcomes show as a message in the form, and the answers stay:
| What happened | The form says |
|---|---|
| The email already has an account | "This email already has an account. Sign in, then connect GitHub." with a Sign in link |
| The provider account is already linked to an account | The visitor is signed in and the page goes where a sign-in button would send them |
| The visitor cancelled at the provider | "Sign-in was cancelled. You can try again whenever you are ready." |
| The browser blocked the window | "Your browser blocked the GitHub window. Allow pop-ups for this site, then try again." |
| The visitor came back while the window is still open | "Finish signing in with GitHub in the window that opened. Closed it? Click the button again." |
| The window was finished more than ten minutes after it opened | "That sign-in took too long. Please try again." |
What a sign-up fills
Sign-up data decides it for the whole site. Out of the box a sign-up fills the email, first name and last name.
- Fields in the form that are chosen for a piece of sign-in data get it. A dropdown or radio field takes it only when it matches one of its choices, a date field only a whole date, a URL field one link, and a one-line field gets several lines on one.
- Anything the provider did not send leaves its field as the visitor left it, and a required field the provider fills is not required for that sign-up.
- Not in the form. What the form has no field for is saved to the new account's profile once the account exists. A field that already has a value keeps it.
- Names. A full name is split at the first space, and a single name becomes the first name. Apple gives a first and last name only the first time a person signs in to your site with Apple.
- Email. Every provider gives a verified address. A Hide My Email relay address is accepted.
Signed up with
The block is also a hidden field of the form, labelled Signed up with unless you change its
Label. It holds the provider's name, such as Google, for a provider sign-up and is empty for
any other. The server sets it, so a value someone types into the request is ignored. It shows in
submissions and in every integration's field picker.
Email verification and signing in
While new accounts must confirm their email, Skip email verification for social sign-ups decides provider sign-ups:
- On, a provider sign-up through the form is confirmed from the start, gets no confirmation email and is signed in at once.
- Off, it gets the confirmation email and stays signed out until the visitor confirms, like any other sign-up.
Without email verification, a provider sign-up is always signed in at once. Whenever it ends signed in, the form's message is replaced with "Your account is ready, and you are signed in."
Inside a sign-in form
In the Login form, the block shows the usual Sign in with Google and other buttons: one click
signs the visitor in, and the form is not sent. It goes to the block's Redirect after sign-in
page, else to the form's own redirect, else to the ?redirect_to= the page was opened with, else
where signing in usually goes.
When visitors do not see it
Inside a form, visitors see no buttons when the form is not used for Registration or Login, none of the block's providers is set up, or, in a sign-up form, it has no Email Address field, the block has no field name, or the site and its admin use different addresses. The editor shows the reason on the block's toolbar and in its sidebar, such as Use this form for Registration or Login in User Profiles › Forms and pages, or visitors will not see this button., with a Choose the forms link.
Existing accounts
Matching email addresses never sign anyone in or merge accounts. If a visitor signs in with a provider whose verified email already belongs to an account here, they are asked to sign in to that account the usual way and link the provider from their account page.
Each account can link one account per provider, and a provider account can belong to only one account on the site. Accounts made by a provider sign-up start without a password their owner knows. Until they set one, they cannot unlink their last sign-in method; they are asked to set a password first, with a link to the password reset page.
New accounts
Accounts are made only by a sign-up form holding the Social Login block. Buttons anywhere else, on a page, the WordPress login screen or the profile screen, sign in people who already have an account, and point someone new to your sign-up page (see Messages).
The sign-up form decides everything about the new account, as for any sign-up: Anyone can register must be on, and the role, log-in and email verification come from the Settings card's Registration group and the form (see Role safety). The one difference is Skip email verification for social sign-ups.
Privacy and security
- Provider tokens are used once to read the account and then thrown away. Nothing is stored except which provider account is linked to which user, and the profile data a sign-up fills by your choice on Sign-up data, including the photo's address when it is shown as the user's picture.
- Extra permissions are asked for only on a sign-up through a form, only while a field takes what they add, and read once, during that sign-up.
- A sign-in started in one browser can only finish in that browser, within ten minutes, once. Changing a provider's keys cancels sign-ins in progress.
- A provider sign-up through a form leaves a pass for the form's submission. It lasts ten minutes, works only in the browser that opened the provider's window and only for that form, and makes one account. A submission that makes no account leaves it unused, so fixing the form and sending it again still works.
- Pending sign-ins and sign-up passes are encrypted with a key from your WordPress salts. PHP's OpenSSL extension is required.
- Each visitor address can start 30 sign-ins a minute. Behind a reverse proxy or CDN, define
XPAC_TRUST_PROXYastrue, or returntruefrom thexpac_trust_proxy_headersfilter; otherwise every visitor shares the proxy's address and its limit. Proxy ranges come from thexpac_forms_trusted_proxiesfilter, Cloudflare's by default. - Provider secrets are write-only for the AI agent: it can save them but never reads them back.
Sign-up data
Providers send more than an email: a name, often a photo, and whatever people put on their profile there, from a bio or a website to the day they joined. Social Login → Sign-up data chooses, once for the whole site, which profile field each piece fills when someone signs up with a provider.
The screen lists your providers, marked Set up or Not set up, with a Social Login link to their keys. Below, the sign-in data in four groups, one row per piece: which providers send it and the profile field it fills. Each list offers only the fields that can hold that data, and Don't fill. Change what you need and save: Saved. New sign-ups fill these fields.
| Sign-in data | Sent by | Fills |
|---|---|---|
| Every provider | An email field. Every new account gets this address, so it cannot be left out. | |
| Email verified | Every provider | A radio or dropdown field with Yes and No choices. |
| Display name | Every provider | A text field, such as a nickname. Apple sends it only the first time. |
| First name, Last name | Every provider | A text field. Apple sends names only the first time; GitHub and Discord send one name, split at the first space. |
| Username | GitHub, Discord | A text field |
| Photo | Google, GitHub, Discord | The avatar field, or Use as the user's photo |
| Bio | GitHub | A textarea, or a text field on one line |
| Location | GitHub | A text field |
| Company | GitHub; Google with Job title and company | A text field |
| Job title | Google with Job title and company | A text field |
| Website | GitHub | A URL or text field. An address without https:// gets it. |
| Twitter / X | GitHub; Discord with Linked accounts | A text field (the handle) or a URL field (its x.com link) |
| Social links | GitHub with Social links; Discord with Linked accounts | A textarea, one link per line, or a URL field, which gets the first |
| Language | Google, Discord | A text or dropdown field |
| Profile link | Google, GitHub | A URL or text field |
| Joined | GitHub, Discord | A date or text field |
| Workspace domain | A text field. Only Google Workspace accounts have one. | |
| Private relay email | Apple | A radio or dropdown field: Yes for a Hide My Email address |
| Available for hire | GitHub | A radio or dropdown field with Yes and No choices |
| Banner | Discord | A URL or text field |
| Accent colour | Discord | A text field, such as #5865f2 |
| Organisations | GitHub with Organisations | A textarea, one per line, or a text field |
| Phone | Google with Phone number | A phone or text field, such as +14155552671. Google does not check that it is theirs. |
| Birthday | Google with Birthday | A date or text field. A birthday without its year reads --05-17, which only a text field holds. |
| Gender | Google with Gender and pronouns | A dropdown, radio or text field |
| Pronouns | Google with Gender and pronouns | A text field |
| Address | Google with Address | A textarea, or a text field on one line |
- Photo. In the avatar field the photo becomes the user's avatar, as if they had uploaded it. Use as the user's photo shows it as their picture across the site until they upload their own. A user who already has an avatar keeps it.
- Only what you choose is kept. Data with no field chosen is never saved anywhere.
- No password. The Password field is never offered.
Extra permissions
Some data comes only with a permission sign-in itself does not need. Each is off until you turn it on, and people are asked for it on the provider's screen when they sign up.
| Extra permission | Provider | Adds | Asks people for |
|---|---|---|---|
| Phone number | Phone | user.phonenumbers.read | |
| Birthday | Birthday | user.birthday.read | |
| Gender and pronouns | Gender, Pronouns | user.gender.read | |
| Address | Address | user.addresses.read | |
| Job title and company | Job title, Company | user.organization.read | |
| Social links | GitHub | Social links | Nothing more |
| Organisations | GitHub | Organisations | read:org |
| Linked accounts | Discord | Twitter / X, Social links | connections |
Google must verify your app
Google's extra permissions are sensitive. Until Google verifies your app, people see an unverified-app screen and at most 100 people can sign in with it. Turn on the People API in your Google Cloud project, add the scopes to your consent screen, and submit the app for verification.
- Asked only when it fills a field. A permission is asked for only on a sign-up through a form, and only while a field is chosen for something it adds. Signing in and linking never ask for it.
- People may say no. Someone who refuses a permission still signs up; its fields are simply not filled.
- GitHub shows an organisation that limits app access only once an owner of it approves your app.
- Discord shares only linked accounts the person shows on their profile and Discord has checked.
Moved from Community Platform
Profile fields, users' photos, the account area, the directory, privacy and suspension used to be
part of Community Platform. Everything about them now belongs to User Profiles: the fields and the
built-in ones, users' answers and photos, profile completion, the profile blocks, {{key}} in text,
the account menu, the account page, the profile page, signed-in only pages, onboarding, keeping
users out of wp-admin, the Group block's User permission and Privacy Relations, the Users
Query blocks, the Search page, each user's privacy choices, suspension and the welcome,
password-reset and incomplete-profile notices. Community Platform keeps connections, messaging and
reports, adds its My Connections choice and connection filters to User Profiles, and reads
every profile value from User Profiles. Community's notifications are now sent by XPAC:
Notifications, which Community Platform needs.
Updating needs nothing from you. Fields, answers, photos, sign-up and profile forms, account pages and your header's account menu keep working. Each move copies, checks the copy, and only then switches to it. Until the check passes, everything keeps working from the old place and an admin notice says so; it tries again on its own.
Blocks with new names
| Block | New name | Old name |
|---|---|---|
| Profile field | xp/profile-field | xp/cp-profile-field |
| User Profile Data | xp/profile-data | xp/cp-profile-data |
| Avatar Upload | xp/avatar-upload-field | xp/cp-avatar-upload-field |
| User Profile Dropdown | xp/account-menu | xp/cp-user-profile-dropdown |
| Profile Completion Banner | xp/profile-completion-banner | xp/cp-profile-completion-banner |
| Profile Completion Tracker | xp/profile-completion-tracker | xp/cp-profile-completion-tracker |
| User Avatar | xp/member-avatar | xp/cp-member-avatar |
| Display Name | xp/member-name | xp/cp-member-name |
| Users Query (was Members Query) | xp/users-query | xp/cp-users-query |
| Users Query Total (was Members Query Total) | xp/users-query-total | xp/cp-users-query-total |
| Privacy Preference | xp/privacy-setting | xp/cp-privacy-setting |
The update renames the blocks in your saved posts, block widgets and global styles, and the last three in old revisions too. The old names are not registered any more, so a theme file, a pattern or an import that still uses one shows nothing until it is changed to the new name. Reload any editor left open during the update before saving. Old and new CSS classes are printed side by side.
What you will notice
- Community Platform needs User Profiles. The Community Platform plugin does not activate without XPAC: User Profiles. If User Profiles goes missing anyway, Community shows a notice and stays off, but signed-in only pages, the account page and signed-in only post types stay closed to signed-out visitors.
- Users are managed here. Community's app no longer has a Profile group, and its old links open User Profiles. A reported member opens in User Profiles when you may open it. The WordPress Users screen no longer has Community's Account type, Career Status and Location columns or its Export button: use the columns and Export CSV of Users.
- Photos move folder. Users' photos move from
uploads/xp-cp/avatars/touploads/xp-up/avatars/. Every file is copied and checked first, the old folder stays, and a photo missing from the new folder is still shown from the old one. If your uploads are kept off the server or cannot be written, photos stay in the old folder and keep working. - Initials pictures. A user without a photo gets a picture with their initials, and a picture another plugin sets for them is kept.
- Avatar uploads work on every site, and take a dropped photo.
- Profile completion is worked out on every save, not only when the banner shows. The incomplete-profile reminder skips users whose profile is complete enough.
- User Avatar and Display Name have no link when the site has no profile page, and the name is escaped and updates as soon as the user saves.
- Signed-out visitors' return address on signed-in only pages is encoded, so it survives every login form.
- After confirming an email, users go to
/dashboardonly where Community Platform found that page published; elsewhere they see the account activated message. Change it in the Access group. - Groups shown to guests, signed-in users or the profile owner keep working without Community Platform, under Visibility Options › User permission.
- Community's messaging page sends signed-out visitors to your login page and back, with the conversation they asked for.
- User notices need XPAC: Notifications. The welcome, password-reset and incomplete-profile notices are User Profiles' now and are sent through XPAC: Notifications. Their switches moved from Community's notification settings to the Notifications screen, under Users, with your saved values. A user who signs up through a form without a password field gets WordPress's new-account email with the link to set one, as well as the welcome. WordPress's email is held back only for a sign-up whose welcome email really went out. A password change sends one email, WordPress's own, so Password reset keeps only its On-site switch. See User notices.
- Privacy follows one rule. Only me and admins now hides an answer from other signed-in users everywhere it prints, not only on the profile page. My Connections shows to the owner, administrators and connections everywhere. Choices users saved carry over.
- The Search page moved from Community → Settings → Pages to the Pages group on Login → Forms and pages, with your saved page. Search changes only while a page is set.
- Suspension and the Include in user search row (it was "Include in user connections and search") come from User Profiles and work without Community Platform.
- Privacy Relations is part of the Group block's Visibility Options panel, next to User permission.
- Community's settings screen no longer shows Member-only pages, Member-only CPT, Require account verification to access member-only pages, Onboarding pages or Mandatory onboarding. They are in the Access group on Login → Forms and pages, with your saved values, as Signed-in only pages, Signed-in only post types and Require account verification for signed-in only pages.
- Gamification lists Fills a profile field and Completes the profile (100%) under User Profiles, and both work without Community. The rules you saved keep working.
- Profile values are escaped wherever the profile data block or
{{key}}prints them.
What your forms send now
Community Platform sent the profile fields on your forms as plain text. User Profiles sends them like other fields:
- Choices (dropdown, radio buttons, checkboxes) send their labels instead of their raw values wherever other choice fields do: Airtable, Brevo, SendGrid emails, Zapier with Send choice labels on, and the notification email.
- Phone numbers get the field's format, so Brevo, GetResponse and Klaviyo receive them with a calling code.
- Files follow the file rules: uploads are checked against the field's file types, size and count, and integrations get links or attachments. Webhooks and Zapier need Forward public file URLs on to send them: with it off, All fields leaves the file out, and a Selected fields row for it stops the webhook or Zap from sending.
Check your automations first
If a Zap, webhook receiver or other automation reads the raw values, update it to read the labels and formatted numbers these forms now send.
Moving from User Auth and Social Login
User Auth and Social Login are part of User Profiles now. Installing it is all you do:
- The old plugins are switched off. An active User Auth or Social Login plugin is turned off when User Profiles is activated, and on the next page load after that. A notice says "User Auth and Social Login are part of User Profiles now, so their old plugins were turned off. You can delete them."
- Everything carries over. Sign-in forms and their settings, the six pages, email verification, linked sign-in methods, provider keys, Sign-up data and the Social Login sign-in buttons keep working with no step from you.
- Deleting the old plugins removes nothing but their files: tables, settings and linked accounts stay.
- Multisite. A network-active old plugin is turned off only when User Profiles is network-active too. Otherwise Network Admin asks you to turn it off there.
- Old links still work. The old Social Login settings page and Forms → Settings → User Auth open the new screens, and the old documentation pages redirect here.
- The editor's User Auth panel is gone. Its saved forms keep running, and a form's task is chosen
on Login → Forms and pages. The editor JavaScript filter
xpac-forms-user-auth-action-settings-before-mappingno longer fires.
Do not go back to an older User Profiles
Once your account forms use the Password field, keep this version or a newer one. An older User Profiles would store typed passwords as profile answers.
Build it with the AI agent
With XPAC Agent active, the agent can set up sign-in, shape your profile fields and look after users. Its tools are on three tabs under XPAC → AI Agent → Tools. Ask for "sign-in and sign-up pages", or pick Login and sign-up pages in a new chat.
Login tab
| Switch | What it does |
|---|---|
| Read the sign-in setup | Reads each kind's form and page on User Profiles › Forms and pages, the registration and access settings, and what is broken. |
| Read a form's auth action | Reads how a form signs people in, registers them, changes their profile or resets a password. |
| Build an auth form | Creates a sign-in form; with assign, its page too, like Create on User Profiles › Forms and pages. |
| Set a form's auth action | Gives a form a sign-in action; with assign, makes it the one its kind uses. |
| Change the sign-in settings | Sets the pages, email verification, the registration role, logging in after registration, who can register, Public Profiles, and signed-in only and onboarding pages. |
| Build sign-in pages | Builds several sign-in forms and pages at once, as drafts or live. |
User Profiles tab
| Switch | What it does |
|---|---|
| List profile fields | Lists the field sets and the profile fields in each, with how many forms and answers use them. |
| Read a profile field | Reads one profile field: its type, help text, choices, rules and the forms that hold it. |
| Add a profile field | Adds a profile field to a field set. |
| Change a profile field | Changes a profile field's label, type, help text, choices, rules or field set. |
| Delete a profile field | Moves a profile field to the trash. Users' saved answers stay. |
| Add a field set | Adds a field set to group profile fields. |
| Change a field set | Renames, describes or moves a field set. |
| Delete a field set | Deletes an empty field set. |
| List users | Finds users by name, email, role or status, without their profile values. |
| Read a user | Reads one user: roles, sign-in methods and every profile field's value, never a password. |
| Change a user's profile | Changes a user's saved profile values. Never a password. |
| Remove a user's photo | Removes the photo a user uploaded. |
| Change the password rules | Sets how strong a password must be and whether people can show it. |
| Put profile fields in a form | Puts profile fields into a form, before its submit button or a field. |
| Suspend user | Suspends a user or lets them back in. Never your own account or an administrator's. |
Social Login tab
| Switch | What it does |
|---|---|
| Read the Social Login setup | Reads which sign-in providers are set up, the sign-in switches, and which forms hold sign-in buttons. |
| Add sign-in buttons to a form | Adds sign-up or sign-in buttons, such as Google or GitHub, to a registration or login form. |
| Read the sign-up data | Reads which profile field each piece of sign-in data fills, and the extra permissions. |
| Change the sign-up data | Changes which profile field each piece of sign-in data fills, and the extra permissions. |
| Change the Social Login settings | Switches providers on or off and saves their keys; secrets are never shown again. |
The rules:
- Passwords never. No tool reads, sets or returns a password.
- Secrets are write-only. The agent can save a provider's secret but never reads it back; results say only whether one is saved.
- No admin roles. It never gives new users the Administrator or Editor role, or one with powers like theirs, and never puts a role on a profile form (see Role safety). The admin's own Email Address is locked.
- What waits for Allow. In the chat, changing the sign-in settings, a user's profile or photo, Sign-up data or the Social Login settings always waits for your Allow. So does setting a form up as a task's form, giving a role, publishing sign-in pages, changing a form that is live, changing the password rules while a form uses the Password field, and deleting a field or a set.
- Undo for 7 days. Every change can be undone from the chat for 7 days, except removing a photo, which says so.
- Over MCP nothing waits. An AI app connected over MCP runs the same tools without asking.
Troubleshooting
| Problem | Check |
|---|---|
| A row on Login → Forms and pages shows a warning | Each warning names what to change. |
| Log in still opens the WordPress login screen | The Login row must show no warning. Inside wp-admin, WordPress's own login screen stays. |
| Reset emails still open the WordPress login screen | The Reset password row must show no warning. |
| The verification link shows no button | The Account verification page must show the Account verification form. |
| The login and registration pages send you away | You are signed in. Check them in a private window. |
| The provider's window does not open | The browser blocked it, and the form says so. Allow pop-ups for the site. Google does not allow signing in inside some in-app browsers; open the page in the phone's own browser. |
| A sign-in button is missing from a form | Select the block in the editor: its sidebar says why. See When visitors do not see it. |
| The editor says the site and its admin use different addresses | The site, its admin and its REST API must share one address, including https and the port. Check Settings → General. |
| The provider's window stays open saying You can close this window | Some browsers do not let it close itself. Click Close this window; the form still gets the result. |
| A provider sign-up says registration is not open | Settings → General → Anyone can register is off. |
| A new account from a provider sign-up is not signed in | Email verification is on and Skip email verification for social sign-ups is off. The visitor confirms by email first. |
| The Login group is missing from the sidebar | An old User Auth or Social Login plugin is still running, or you lack the sign-in capability. Turn the old plugin off. |
| An admin notice says User Profiles has not finished moving | Everything keeps working from the old place, and it tries again on its own. The notice says what is left. |
| No welcome or reminder notices are sent | XPAC: Notifications must be active, with the notice switched on under Users on its screen. |
| A directory or privacy block shows nothing on a theme page | The theme file still uses an old block name, such as xp/cp-users-query. Change it to the new name. |
| A notice says to update Community Platform to finish moving | An older Community Platform is still running the directory and privacy. Update it. |
Uninstalling
Deleting User Profiles keeps your fields, field sets, answers, photos, sign-in forms and pages, and
their settings. It removes its upgrade records and scheduled jobs, pending sign-ins, sign-up passes and
Social Login's hourly clean-up. Linked sign-in methods, provider keys, Sign-up data and the extra
permissions stay, because accounts made by a provider sign-up could not sign in after a reinstall
without them. To remove those too, return true from the
xpac_social_login_remove_data_on_uninstall filter in a must-use plugin before deleting. Nothing is
removed while another installed XPAC plugin, such as an old Social Login, still includes Social
Login.
For developers
Storage
- Fields are
profile-fieldposts: the title is the label, the slug is the key, the content is one Forms field block andmenu_orderis its position in its set. - Field sets are terms of the private taxonomy
xpac_profile_field_set, with their position in the term metaxpac_order. The Account set carriesxpac_built_in. - Answers live in the
{prefix}xp_up_profile_answerstable, one row per person and field key. The four account fields are read from and written to the WordPress user. Checkboxes are stored comma-joined, and clearing an answer deletes its row. The Password field is never stored. - Photos: the user meta
xpac_user_profiles_avatar(size => file name), with the files underuploads/xp-up/avatars/<user id>/. Profile completion is the user metaxpac_user_profiles_completion; onboarding isxpac_user_profiles_onboarded. - Settings live in the option
xpac_user_profiles, under their old key names:page_login,page_registration,page_forgot_password,page_reset_password,page_account_verificationanduser_auth_email_verification(fromxpac_forms),page_account,page_memberOnly,member_only_cpt,verified_account_for_member_only_pages,page_onboardingandmandatory_onboarding(fromxpac_community_platform), and the newadmin_guard,after_verification_urlandopen_verification_to_members. A key it does not hold yet is read from its old option: a sign-in key fromxpac_forms, and a Community key fromxpac_community_platformonly while Community runs and until the upgrade copied it. Writes of sign-in keys are copied back toxpac_forms; nothing is written toxpac_community_platform. - Sign-in forms: a form does a task while its
form_settingsmeta holds a switched-onuserAuthitem of that action. Three options, not autoloaded, sit beside it:xpac_user_profiles_account_forms(the form picked per task),xpac_user_profiles_account_seed(what activation made) andxpac_user_profiles_account_seeding(a lock). - Other options:
xpac_user_profiles_upgradecounts the upgrade steps run,xpac_user_profiles_movesfollows each move,xpac_user_profiles_retired_noticeholds the old plugins' notice until it shows,xpac_user_profiles_password_conflictmarks a site where another field holds the keypassword, andxpac_user_profiles_completion_refreshholds the background completion refresh's place while it runs. - Social Login:
xpac_social_login_settings(switches and keys),xpac_social_login_profile_mapandxpac_social_login_extras(Sign-up data), the tables{prefix}xp_social_login_identities,_statesand_limits, and the user metaxpac_social_login_passwordless,xpac_social_login_signed_up_withandxpac_social_login_photo. - Email verification: the table
{prefix}xp_signups; a pending email change is the user meta_new_email. - Privacy: the user meta
xpac_user_profiles_privacy({settingId: choice}), read from Community'sxpac_community_privacy_settingsuntil the upgrade copied it. - Directory: the Search page is
page_searchinxpac_user_profiles; the users left out are the optionxpac_user_profiles_directory_excluded. - Suspension: the user meta
is_suspended(1when suspended). - Cron:
xpac_user_profiles_upgrade,xpac_user_profiles_refresh_completion,xpac_user_profiles_incomplete_profile_check(daily, only with XPAC: Notifications) andxpac_social_login_cleanup.
Uninstalling deletes the upgrade, moves, sign-in form, notice and refresh options and their cron events. Fields, sets, answers, photos, settings and Social Login's data stay.
REST
Namespace xpac/v1. Users and Profile fields need the capability from
xpac_user_profiles_capability; sign-in setup needs the one from xpac_user_profiles_login_capability.
Both are manage_options by default.
| Route | Does |
|---|---|
user-profiles/admin/fields, …/fields/<id>, …/sets, …/sets/<id>, …/order | The Profile fields screen. |
user-profiles/admin/users, …/users/meta, …/users/<id>, …/users/<id>/avatar, …/users/export, …/users/columns | User Profiles and each person's page. |
user-profiles/admin/account-forms | GET and PUT the rows of Login → Forms and pages and the registration settings. |
user-profiles/admin/account-forms/<kind>/create | POST makes a task's minimal form and page (201). |
social-login/admin/settings | GET and PUT {values: {name: value}} the Social Login settings. A refused value is a 400 and nothing is stored. |
social-login/admin/profile-map | GET and PUT {map?, extras?} Sign-up data. |
user-profiles/form-fields, user-profiles/admin/fields/from-block | The profile field block in the editor. |
user-profiles/directory | POST, signed in: the next page of Users Query cards. The old cp/members answers too. |
privacy-settings/ | PUT, PATCH or POST, signed in: {settingId: choice} for the current user; 422 on an empty or unknown value. |
…/users/meta describes the list's columns for DataViews. The list and the export take DataViews'
view: search, orderby, order, page, per_page (up to 100, or 200 for the export) and
filters. Saving a person's answers or removing their photo also needs the right to edit that user.
Sign-in itself runs through Forms' public submit route,
POST /wp-json/xpac/v1/form/<form-id>/<instance>/submit, and a provider sign-up's window reports at
GET /wp-json/xpac-social-login/v1/form-attempts/<attempt>.
Blocks and assets
The blocks are listed under Blocks for profiles, plus Social Login's
xp/social-login, xp/social-login-button and xp/connected-accounts, and the Password field
xp/form-field-password. Old block names are not registered; hook render_block_<name> on the new
name.
The Profile Dropdown is three blocks: xp/profile-dropdown, with its xp/profile-dropdown-toggle
and xp/profile-dropdown-panel. Its menu is a core/navigation block of core/navigation-link
page links, followed by core/loginout.
Built files are under dist/packages/user-profiles/: the admin app (admin/), the profile-field
post editor (post-editor/), the sign-in front script (auth/front.js), the Password block
(auth/blocks/), the profile, directory and privacy blocks (blocks/), the Group panel
(extensions/visibility), the Autocomplete Search additions (extensions/search, handle
xpac-user-profiles-search) and Social Login's blocks (social-login/blocks/). The Users Query
slider uses the shared xp-swiper handle. The Privacy Preference block gets
window.xpacUserProfilesPrivacy on the page and window.xpacUserProfilesPrivacyEditor in the
editor. The account menu is a React app built to
blocks/account-menu/app/ on XPAC's shared React runtime, dist/packages/react-runtime.
<!-- wp:xp/social-login {"providers":[],"size":"large","iconPosition":"edge","redirectTo":"/account/","className":"is-style-brand"} -->
<!-- wp:xp/social-login-button {"provider":"google"} /-->
<!-- wp:xp/social-login-button {"provider":"apple","label":"Continue with Apple"} /-->
<!-- /wp:xp/social-login -->
<!-- wp:xp/connected-accounts {"redirectTo":"/account/"} /-->Request path
A sign-in form runs inside Forms' submit route as one mutation, after Forms' own checks, and a
refusal returns before the submission is stored. Credentials are removed in a finally block, and
Forms' request guard records field names, never values. Sessions are WordPress's: wp_signon() for
login, and wp_set_auth_cookie() after a registration that signs in. A request with no
X-WP-Nonce is treated as signed out, which stops a profile form being driven cross-site.
Styling
| Selector | What it is |
|---|---|
.wp-block-xp-profile-field | A profile field in a form (also .wp-block-xp-cp-profile-field) |
.xp-profile-data, .xp-profile-data__<key> | A profile data block (also .xp-cp-profile-field, .xp-cp-profile-field__<key>) |
.xp-account-menu | The account menu (also .xp-user-profile-root, styled with --xp-profile-*) |
.is-dropping | An Avatar Upload field while a photo is dragged over it; its picture has data-hover-label and data-drop-label |
.wp-block-xp-social-login, .wp-block-xp-social-login-button | Sign-in block and its buttons |
.xpac-social-login-button | Every provider, Link and Unlink button, plus --google, --icon-only and so on |
.xpac-social-login-icon | Provider logo; size it with --xpac-social-login-icon-size |
--xpac-social-login-height | Button height (2.75rem; 2.25rem small, 3.25rem large) |
.xpac-social-login-notice, .xpac-social-login-status | Outcome message, and the line under a sign-up button |
.xpac-social-login-account | One Connected Accounts row, with --linked or --unlinked |
.wp-block-xp-users-query, .xp-user-card, .xp-user-card__avatar, __name, __actions | Users Query and its cards (also the old xp-cp-* classes) |
.xp-privacy-setting, .xp-privacy-select | Privacy Preference (also .xp-cp-privacy-setting, .xp-cp-privacy-select) |
A sign-in form's <form> carries data-xpac-account-form="<kind>", such as registration.
Popups' form triggers and Analytics' form events leave such forms out.
Hooks
New with this version:
| Hook | Type | Arguments |
|---|---|---|
xpac_user_profiles_login_capability | filter | string $capability (default manage_options) |
xpac_user_profiles_social_login_state | filter | array $state, bool $secrets |
xpac_user_profiles_social_login_settings_updated | action | string[] $names, array $state (no secrets) |
xpac_user_profiles_account_kinds | filter | array $kinds |
xpac_user_profiles_account_form_blocks | filter | string[] $blocks, string $kind, array $definitions |
xpac_user_profiles_account_form_args | filter | array $postarr, string $kind |
xpac_user_profiles_account_page_args | filter | array $postarr, string $kind, int $formId |
xpac_user_profiles_account_forms_state | filter | array $state |
xpac_user_profiles_seed_account_forms | filter | bool $seed (default true) |
xpac_user_profiles_account_form_badge | filter | array|null $badge, string $kind, WP_Post $form |
xpac_user_profiles_account_form_assigned | action | string $kind, int $formId, int $previousFormId |
xpac_user_profiles_account_page_assigned | action | string $kind, int $pageId, int $previousPageId |
xpac_user_profiles_account_form_created | action | string $kind, int $formId, int $pageId |
xpac_user_profiles_account_settings_updated | action | array $settings, array $previous |
xpac_user_profiles_account_forms_seeded | action | array $created (kind => {form, page}) |
xpac_user_profiles_account_field_targets | filter | array $targets, ?Submission $submission |
xpac_user_profiles_account_rows | filter | array $rows, string $action, bool $mapped, Submission $submission |
xpac_user_profiles_check_password_strength | filter | bool $check, string $action, int $formId |
xpac_user_profiles_write_only_fields | filter | string[] $keys |
xpac_user_profiles_agent_locked_answers | filter | string[] $keys, WP_User $member |
xpac_user_profiles_agent_member | filter | array $view, WP_User $member |
xpac_user_profiles_retired_plugins | filter | array $plugins (folder => name) |
xpac_user_profiles_retired_plugins_deactivated | action | string[] $basenames, bool $networkWide |
xpac_user_profiles_member_url | filter | string $url, WP_User $user |
xpac_user_profiles_displayed_user_id | filter | int $userId |
xpac_user_profiles_signed_in_landing | filter | string $url, WP_User $user |
xpac_user_profiles_allow_admin_access | filter | bool $allowed, WP_User $user |
xpac_user_profiles_protected_page_redirect | filter | string|null $url |
xpac_user_profiles_directory_query_args | filter | array $args, array $attributes, bool $front |
xpac_user_profiles_directory_excluded_users | filter | int[] $ids |
xpac_user_profiles_directory_context_free_filters | filter | string[] $filters (default ['']) |
xpac_user_profiles_directory_card_actions | filter | string $markup, WP_User $user, array $attributes |
xpac_user_profiles_privacy_choices | filter | array $choices (id => title, description, icon) |
xpac_user_profiles_privacy_match | filter | bool $match, string $choice, int $ownerId, int $viewerId, string $settingId |
xpac_user_profiles_privacy_values | filter | array $values, int $userId, string $relation |
xpac_user_profiles_user_suspended | action | int $userId, bool $suspended |
xpac_user_profiles_incomplete_profile_threshold | filter | int|float $threshold (default 80; 0 or less turns the reminder off) |
xpac_forms_admin_form_badges | filter | array $badges, WP_Post $form |
xpac_forms_admin_moved_settings_pages | filter | array $moved (page name => URL) |
xpac_forms_ability_field_types | filter | array $types (type => block name) |
xpac_forms_ability_field_warnings | filter | array $warnings, array $fields |
Renamed. The new name runs first; the old one still runs after it with the same arguments, deprecated since 1.0.0:
| Old | New |
|---|---|
xp_cp_avatar_sizes | xpac_user_profiles_avatar_sizes |
xp_cp_render_profile_data | xpac_user_profiles_render_profile_data |
xp_cp_save_profile_fields | xpac_user_profiles_save_profile_fields |
xp_cp_user_profile_fields | xpac_user_profiles_user_profile_fields |
xpac_cp_members_excluded_dynamic_vars | xpac_user_profiles_excluded_dynamic_vars |
xpac_community_platform_profile_field_saved | xpac_user_profiles_profile_field_saved |
xpac_cp_allow_admin_access | xpac_user_profiles_allow_admin_access |
xp_cp_members_user_redirect_url_on_protected_page_access | xpac_user_profiles_protected_page_redirect |
Renamed the same way, deprecated since 1.1.0:
| Old | New |
|---|---|
xpac_cp_members_query_loop_args | xpac_user_profiles_directory_query_args |
xp_cp_excluded_users_in_members_query | xpac_user_profiles_directory_excluded_users |
xp_cp_block_visibility_privacy_based_values | xpac_user_profiles_privacy_values |
xp_cp_incomplete_profile_notification_threshold | xpac_user_profiles_incomplete_profile_threshold |
xp_cp_check_member_incomplete_profile (cron action) | xpac_user_profiles_incomplete_profile_check |
xpac-cp-member-query-filter-by (JS) | xpacUserProfiles.directory.filterOptions (JS) |
PHP functions: xpac_user_profiles_displayed_user_id(): int and
xpac_user_profiles_profile_url(int $userId): string, which is '' when the site has no profile
page. Core\Privacy (register(), get(), save(), canView()), Core\Directory and
Auth\Core\Suspension (isSuspended(), set()) are the PHP entry points for other plugins.
Kept with the same names and arguments:
xpac_user_profiles_capabilitygates Users and Profile fields: the screens, their routes and the AI tools.xpac_user_profiles_admin_boot,_admin_dependenciesand_admin_enqueueextend the admin app. The JS filtersxpacUserProfiles.admin.groupsand.tabskeep their names; the base groups areusersandlogin, and a group added under the old idsprofileorsign-inlands in them.xpac_social_login_settings_pagefires when the User Profiles screen loads, for people who may set up sign-in, andwp_react_settings_after_module_settings_saveon every Social Login save.xpac_forms_user_auth_profile_fieldsalso answerscredentials, andxpac_user_auth_form_actionalso answers for forms whose profile fields fill the account.xpac_user_auth_agent_setupcarriesaccount_forms,registration,forms_urlandaccount_pages.- Every other
xpac_forms_user_auth_*,xpac_user_auth_*,xpac_social_login_*andxpac_user_profiles_*hook, and the Forms hooks the sign-in code answers. xpac-forms-user-auth-action-settings-before-mapping(JS) no longer fires, since its panel is gone.
The hook reference lists every hook with its arguments and where it fires.
Changed from Community Platform
- Answers moved from
{prefix}xp_cp_profile_datato{prefix}xp_up_profile_answers, with the same columns and keys. The copy is checked before the switch. The old table stays for now but gets no new answers, so SQL that names it reads old data. - The photo's user meta moved from
xp_cp_avatartoxpac_user_profiles_avatar, profile completion fromxp_cp_profile_completiontoxpac_user_profiles_completion, and the files fromuploads/xp-cp/avatars/touploads/xp-up/avatars/. - Onboarding moved from
onboarding_completetoxpac_user_profiles_onboarded; a write to either is copied to the other. - Community's settings for the account page, the profile page, Public Profiles, signed-in only pages
and onboarding are read from
xpac_user_profilesfirst, withxpac_community_platformas the fallback while Community runs and until the upgrade copies them. On a site where Community is off, its old values are not copied or read. - The profile page belongs to User Profiles, under the same
profilealias, sopages->profile->user,->getUrl($user)and->matchesCurrentPage()work as before. Its addresses carry the user's slug in thexpac_profilequery var;xp_cp_memberis still read.xpac_user_profiles_displayed_user_id()gives the user it shows, 0 elsewhere, andxpac_cp_displayed_user_id()now returns the same. - The account, signed-in only and onboarding pages belong to User Profiles too, under the same
aliases, so
pages->account,->memberOnlyand->onboardingwork as before. Community keeps no copies of these pages. While an old User Auth plugin is still loaded, User Profiles runs them and the profile page by themselves, so the aliases are always there. - Keeping users out of wp-admin, the redirect after confirming an email and the
X-User-Stateheader on WordPress VIP belong to User Profiles too, and Community keeps no copies of them. While an old User Auth plugin is still loaded, User Profiles runs them as well, so users still stay out of wp-admin. - Clearing an answer deletes its row, where Community stored
''. The saved hooks still fire, with''. xpac_user_profiles_user_profile_fieldsgetsCore\Profilesas its third argument, with the same methods as Community's data provider, so drop aDataProvidertype hint.- The
xpacCommunityPlatforminteractivity state no longer hascurrentUser.profileData; profile values, and the current user'savatarUrlanddisplayName, bind to thexpacUserProfilesstate. Community keeps itscurrentUserfor one more release. - Community's admin routes
xpac/v1/cp/admin/profile-fields,xpac/v1/cp/admin/users-data(with/fields,/<id>and/<id>/avatar) andxpac/v1/cp/users-data/export, and the AJAX actionxp_cp_export_users, are gone; thexpac/v1/user-profiles/admin/*routes replace them.xp_cp_users_list_table_columnsis no longer applied. - The after-confirmation redirect is a 302, not a 301.
- The avatar field declares itself a file field, under both its names:
xpac_forms_xp/avatar-upload-field_field_typereturnsfile. xpac_user_profiles_remove_avataris gone: User Profiles keeps the photos and removes them itself.- Community's Members module is gone: every
CommunityPlatform\Modules\Members\*class, includingMembers\Module::$data.CommunityPlatform\Core\PrivacySettingsforwards toCore\Privacyfor one release. Privacy choices moved fromxpac_community_privacy_settingstoxpac_user_profiles_privacy, the left-out users fromxp_cp_exclude_admins_in_members_querytoxpac_user_profiles_directory_excluded, and the Search page fromxpac_community_platformtoxpac_user_profiles. The old values stay this release. - The directory route is
xpac/v1/user-profiles/directory;cp/membersstill answers this release. JS globals:window.xpacCpUsersQueryiswindow.xpacUserProfilesUsersQuery, and the privacy block's globals arewindow.xpacUserProfilesPrivacyandwindow.xpacUserProfilesPrivacyEditor. personal_bio_visibilityis no longer registered; stored values stay.- While an older Community Platform still runs its Members module, User Profiles leaves suspension, the Include in user search row, the Search page, privacy and the user notices to it, and a notice asks you to update it. A new Community Platform on an older User Profiles stays off with "Update XPAC: User Profiles to use Community."
TouchBasePro
Add form sign-ups to a TouchBasePro list and fill its custom fields from their answers.
User Targeting
Add visitor conditions to XPAC Popups and XPAC Forms, so a popup opens or a form section appears only for visitors matching the device, page address, cookie, browser storage value or country you choose.