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.

Under Rules, turn on Required and, if you like, the Message when empty.
Pick the Field set on the right, then click Save field.

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.

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

BlockNameWhat it shows
Profile fieldxp/profile-fieldOne profile field inside a form, filled with the user's answer.
Avatar Uploadxp/avatar-upload-fieldA photo upload inside a form. A user can drop a photo on it.
User Profile Dataxp/profile-dataOne person's answer to a field, as a paragraph.
User Profile Dropdownxp/account-menuThe signed-in user's photo, opening View profile, Settings and Log Out.
Profile Dropdownxp/profile-dropdownThe signed-in user's menu, built from blocks you can change.
User Avatarxp/member-avatarA user's photo.
Display Namexp/member-nameA user's display name.
Profile Completion Bannerxp/profile-completion-bannerA message for users whose profile is not complete enough yet.
Profile Completion Trackerxp/profile-completion-trackerHow complete the user's profile is, as a row of steps.
Users Queryxp/users-queryUsers in a grid or a slider. See Directory.
Users Query Totalxp/users-query-totalHow many users match a filter.
Privacy Preferencexp/privacy-settingLets 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 forWhat it doesIts page
RegistrationCreates accounts.Your sign-up page.
LoginSigns users in.Your sign-in page. WordPress's Log in links open it.
Forgot passwordSends a reset link.Where Lost your password? goes.
Reset passwordSets a new password.Where the emailed reset link lands.
Update passwordChanges the password of a signed-in user.None. Put the form on your account page.
Account verificationResends 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

Open Login → Forms and pages.

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.

In Change…, click Save. The row's warning goes once the form, the page and their settings are right.

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

TaskWhat submitting doesVisitor must be
RegistrationCreates an account from the answersSigned out
LoginSigns the visitor inSigned out
Update (a profile form)Saves changes to the signed-in user's accountSigned in
Forgot passwordEmails the standard WordPress reset linkEither
Reset passwordSets the new password after that link is followedSigned out
Update passwordChanges the signed-in user's password after checking the current oneSigned in
Account verificationSends the verification email againEither

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.

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 the xpac_user_auth_agent_reserved_meta filter.
  • 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 with xpac_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

SettingWhere it is now
Login, registration, forgot password, reset password and account verification pagesLogin → Forms and pages, one row each
Require email verification for new accounts, new users' role, log in after registrationLogin → Forms and pages, Settings, Registration
Public Profiles, Profile page, Search pageLogin → 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 emailLogin → Forms and pages, Settings, Access
Provider keys, buttons on the WordPress login pageSocial Login → Providers
What a provider sign-up fillsSocial 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.

ChoiceWho sees it
EveryoneAnyone, signed in or not.
Only me and adminsThe user and site administrators.
My ConnectionsThe 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=google

Copy 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.

Google

  1. Open the Google card and copy the Callback URL.
  2. In Google Cloud, set up the consent screen and create an OAuth client of type Web application.
  3. Add the callback URL under Authorized redirect URIs.
  4. 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

  1. Open the GitHub card and copy the Callback URL.
  2. 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.
  3. 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.

  1. Open the Apple card and copy the Callback URL.
  2. 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.
  3. On the Services ID, add your website's domain and the callback URL as a Return URL.
  4. Create a Sign in with Apple key and download its .p8 file. Note its Key ID and your membership's Team ID.
  5. Enter the Services ID, Team ID and Key ID. Open the .p8 file 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

  1. Open the Discord card and copy the Callback URL.
  2. Create an application in the Discord Developer Portal and open its OAuth2 page.
  3. Add the callback URL under Redirects.
  4. 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

Open the sign-up form in the form editor and insert the Social Login block where the buttons should go, usually above the first field.
Empty buttons say Sign up with Google, Sign up with GitHub and so on. Click a button's text to change it.
Check the block. When visitors would not see the buttons, a warning on its toolbar and a notice in its sidebar say why.
Update the form.

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

  1. 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.
  2. The form checks those other fields first. If one is wrong, it shows the error in place and nothing else happens.
  3. A small window for that provider opens; the page stays where it is. The visitor signs in there.
  4. 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 happenedThe 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 accountThe 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_PROXY as true, or return true from the xpac_trust_proxy_headers filter; otherwise every visitor shares the proxy's address and its limit. Proxy ranges come from the xpac_forms_trusted_proxies filter, 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 dataSent byFills
EmailEvery providerAn email field. Every new account gets this address, so it cannot be left out.
Email verifiedEvery providerA radio or dropdown field with Yes and No choices.
Display nameEvery providerA text field, such as a nickname. Apple sends it only the first time.
First name, Last nameEvery providerA text field. Apple sends names only the first time; GitHub and Discord send one name, split at the first space.
UsernameGitHub, DiscordA text field
PhotoGoogle, GitHub, DiscordThe avatar field, or Use as the user's photo
BioGitHubA textarea, or a text field on one line
LocationGitHubA text field
CompanyGitHub; Google with Job title and companyA text field
Job titleGoogle with Job title and companyA text field
WebsiteGitHubA URL or text field. An address without https:// gets it.
Twitter / XGitHub; Discord with Linked accountsA text field (the handle) or a URL field (its x.com link)
Social linksGitHub with Social links; Discord with Linked accountsA textarea, one link per line, or a URL field, which gets the first
LanguageGoogle, DiscordA text or dropdown field
Profile linkGoogle, GitHubA URL or text field
JoinedGitHub, DiscordA date or text field
Workspace domainGoogleA text field. Only Google Workspace accounts have one.
Private relay emailAppleA radio or dropdown field: Yes for a Hide My Email address
Available for hireGitHubA radio or dropdown field with Yes and No choices
BannerDiscordA URL or text field
Accent colourDiscordA text field, such as #5865f2
OrganisationsGitHub with OrganisationsA textarea, one per line, or a text field
PhoneGoogle with Phone numberA phone or text field, such as +14155552671. Google does not check that it is theirs.
BirthdayGoogle with BirthdayA date or text field. A birthday without its year reads --05-17, which only a text field holds.
GenderGoogle with Gender and pronounsA dropdown, radio or text field
PronounsGoogle with Gender and pronounsA text field
AddressGoogle with AddressA 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 permissionProviderAddsAsks people for
Phone numberGooglePhoneuser.phonenumbers.read
BirthdayGoogleBirthdayuser.birthday.read
Gender and pronounsGoogleGender, Pronounsuser.gender.read
AddressGoogleAddressuser.addresses.read
Job title and companyGoogleJob title, Companyuser.organization.read
Social linksGitHubSocial linksNothing more
OrganisationsGitHubOrganisationsread:org
Linked accountsDiscordTwitter / X, Social linksconnections

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

BlockNew nameOld name
Profile fieldxp/profile-fieldxp/cp-profile-field
User Profile Dataxp/profile-dataxp/cp-profile-data
Avatar Uploadxp/avatar-upload-fieldxp/cp-avatar-upload-field
User Profile Dropdownxp/account-menuxp/cp-user-profile-dropdown
Profile Completion Bannerxp/profile-completion-bannerxp/cp-profile-completion-banner
Profile Completion Trackerxp/profile-completion-trackerxp/cp-profile-completion-tracker
User Avatarxp/member-avatarxp/cp-member-avatar
Display Namexp/member-namexp/cp-member-name
Users Query (was Members Query)xp/users-queryxp/cp-users-query
Users Query Total (was Members Query Total)xp/users-query-totalxp/cp-users-query-total
Privacy Preferencexp/privacy-settingxp/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/ to uploads/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 /dashboard only 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-mapping no 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

SwitchWhat it does
Read the sign-in setupReads 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 actionReads how a form signs people in, registers them, changes their profile or resets a password.
Build an auth formCreates a sign-in form; with assign, its page too, like Create on User Profiles › Forms and pages.
Set a form's auth actionGives a form a sign-in action; with assign, makes it the one its kind uses.
Change the sign-in settingsSets 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 pagesBuilds several sign-in forms and pages at once, as drafts or live.

User Profiles tab

SwitchWhat it does
List profile fieldsLists the field sets and the profile fields in each, with how many forms and answers use them.
Read a profile fieldReads one profile field: its type, help text, choices, rules and the forms that hold it.
Add a profile fieldAdds a profile field to a field set.
Change a profile fieldChanges a profile field's label, type, help text, choices, rules or field set.
Delete a profile fieldMoves a profile field to the trash. Users' saved answers stay.
Add a field setAdds a field set to group profile fields.
Change a field setRenames, describes or moves a field set.
Delete a field setDeletes an empty field set.
List usersFinds users by name, email, role or status, without their profile values.
Read a userReads one user: roles, sign-in methods and every profile field's value, never a password.
Change a user's profileChanges a user's saved profile values. Never a password.
Remove a user's photoRemoves the photo a user uploaded.
Change the password rulesSets how strong a password must be and whether people can show it.
Put profile fields in a formPuts profile fields into a form, before its submit button or a field.
Suspend userSuspends a user or lets them back in. Never your own account or an administrator's.

Social Login tab

SwitchWhat it does
Read the Social Login setupReads which sign-in providers are set up, the sign-in switches, and which forms hold sign-in buttons.
Add sign-in buttons to a formAdds sign-up or sign-in buttons, such as Google or GitHub, to a registration or login form.
Read the sign-up dataReads which profile field each piece of sign-in data fills, and the extra permissions.
Change the sign-up dataChanges which profile field each piece of sign-in data fills, and the extra permissions.
Change the Social Login settingsSwitches 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

ProblemCheck
A row on Login → Forms and pages shows a warningEach warning names what to change.
Log in still opens the WordPress login screenThe Login row must show no warning. Inside wp-admin, WordPress's own login screen stays.
Reset emails still open the WordPress login screenThe Reset password row must show no warning.
The verification link shows no buttonThe Account verification page must show the Account verification form.
The login and registration pages send you awayYou are signed in. Check them in a private window.
The provider's window does not openThe 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 formSelect 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 addressesThe 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 windowSome 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 openSettings → General → Anyone can register is off.
A new account from a provider sign-up is not signed inEmail 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 sidebarAn 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 movingEverything 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 sentXPAC: Notifications must be active, with the notice switched on under Users on its screen.
A directory or privacy block shows nothing on a theme pageThe 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 movingAn 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-field posts: the title is the label, the slug is the key, the content is one Forms field block and menu_order is its position in its set.
  • Field sets are terms of the private taxonomy xpac_profile_field_set, with their position in the term meta xpac_order. The Account set carries xpac_built_in.
  • Answers live in the {prefix}xp_up_profile_answers table, 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 under uploads/xp-up/avatars/<user id>/. Profile completion is the user meta xpac_user_profiles_completion; onboarding is xpac_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_verification and user_auth_email_verification (from xpac_forms), page_account, page_memberOnly, member_only_cpt, verified_account_for_member_only_pages, page_onboarding and mandatory_onboarding (from xpac_community_platform), and the new admin_guard, after_verification_url and open_verification_to_members. A key it does not hold yet is read from its old option: a sign-in key from xpac_forms, and a Community key from xpac_community_platform only while Community runs and until the upgrade copied it. Writes of sign-in keys are copied back to xpac_forms; nothing is written to xpac_community_platform.
  • Sign-in forms: a form does a task while its form_settings meta holds a switched-on userAuth item 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) and xpac_user_profiles_account_seeding (a lock).
  • Other options: xpac_user_profiles_upgrade counts the upgrade steps run, xpac_user_profiles_moves follows each move, xpac_user_profiles_retired_notice holds the old plugins' notice until it shows, xpac_user_profiles_password_conflict marks a site where another field holds the key password, and xpac_user_profiles_completion_refresh holds the background completion refresh's place while it runs.
  • Social Login: xpac_social_login_settings (switches and keys), xpac_social_login_profile_map and xpac_social_login_extras (Sign-up data), the tables {prefix}xp_social_login_identities, _states and _limits, and the user meta xpac_social_login_passwordless, xpac_social_login_signed_up_with and xpac_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's xpac_community_privacy_settings until the upgrade copied it.
  • Directory: the Search page is page_search in xpac_user_profiles; the users left out are the option xpac_user_profiles_directory_excluded.
  • Suspension: the user meta is_suspended (1 when suspended).
  • Cron: xpac_user_profiles_upgrade, xpac_user_profiles_refresh_completion, xpac_user_profiles_incomplete_profile_check (daily, only with XPAC: Notifications) and xpac_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.

RouteDoes
user-profiles/admin/fields, …/fields/<id>, …/sets, …/sets/<id>, …/orderThe Profile fields screen.
user-profiles/admin/users, …/users/meta, …/users/<id>, …/users/<id>/avatar, …/users/export, …/users/columnsUser Profiles and each person's page.
user-profiles/admin/account-formsGET and PUT the rows of Login → Forms and pages and the registration settings.
user-profiles/admin/account-forms/<kind>/createPOST makes a task's minimal form and page (201).
social-login/admin/settingsGET and PUT {values: {name: value}} the Social Login settings. A refused value is a 400 and nothing is stored.
social-login/admin/profile-mapGET and PUT {map?, extras?} Sign-up data.
user-profiles/form-fields, user-profiles/admin/fields/from-blockThe profile field block in the editor.
user-profiles/directoryPOST, 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

SelectorWhat it is
.wp-block-xp-profile-fieldA 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-menuThe account menu (also .xp-user-profile-root, styled with --xp-profile-*)
.is-droppingAn 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-buttonSign-in block and its buttons
.xpac-social-login-buttonEvery provider, Link and Unlink button, plus --google, --icon-only and so on
.xpac-social-login-iconProvider logo; size it with --xpac-social-login-icon-size
--xpac-social-login-heightButton height (2.75rem; 2.25rem small, 3.25rem large)
.xpac-social-login-notice, .xpac-social-login-statusOutcome message, and the line under a sign-up button
.xpac-social-login-accountOne Connected Accounts row, with --linked or --unlinked
.wp-block-xp-users-query, .xp-user-card, .xp-user-card__avatar, __name, __actionsUsers Query and its cards (also the old xp-cp-* classes)
.xp-privacy-setting, .xp-privacy-selectPrivacy 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:

HookTypeArguments
xpac_user_profiles_login_capabilityfilterstring $capability (default manage_options)
xpac_user_profiles_social_login_statefilterarray $state, bool $secrets
xpac_user_profiles_social_login_settings_updatedactionstring[] $names, array $state (no secrets)
xpac_user_profiles_account_kindsfilterarray $kinds
xpac_user_profiles_account_form_blocksfilterstring[] $blocks, string $kind, array $definitions
xpac_user_profiles_account_form_argsfilterarray $postarr, string $kind
xpac_user_profiles_account_page_argsfilterarray $postarr, string $kind, int $formId
xpac_user_profiles_account_forms_statefilterarray $state
xpac_user_profiles_seed_account_formsfilterbool $seed (default true)
xpac_user_profiles_account_form_badgefilterarray|null $badge, string $kind, WP_Post $form
xpac_user_profiles_account_form_assignedactionstring $kind, int $formId, int $previousFormId
xpac_user_profiles_account_page_assignedactionstring $kind, int $pageId, int $previousPageId
xpac_user_profiles_account_form_createdactionstring $kind, int $formId, int $pageId
xpac_user_profiles_account_settings_updatedactionarray $settings, array $previous
xpac_user_profiles_account_forms_seededactionarray $created (kind => {form, page})
xpac_user_profiles_account_field_targetsfilterarray $targets, ?Submission $submission
xpac_user_profiles_account_rowsfilterarray $rows, string $action, bool $mapped, Submission $submission
xpac_user_profiles_check_password_strengthfilterbool $check, string $action, int $formId
xpac_user_profiles_write_only_fieldsfilterstring[] $keys
xpac_user_profiles_agent_locked_answersfilterstring[] $keys, WP_User $member
xpac_user_profiles_agent_memberfilterarray $view, WP_User $member
xpac_user_profiles_retired_pluginsfilterarray $plugins (folder => name)
xpac_user_profiles_retired_plugins_deactivatedactionstring[] $basenames, bool $networkWide
xpac_user_profiles_member_urlfilterstring $url, WP_User $user
xpac_user_profiles_displayed_user_idfilterint $userId
xpac_user_profiles_signed_in_landingfilterstring $url, WP_User $user
xpac_user_profiles_allow_admin_accessfilterbool $allowed, WP_User $user
xpac_user_profiles_protected_page_redirectfilterstring|null $url
xpac_user_profiles_directory_query_argsfilterarray $args, array $attributes, bool $front
xpac_user_profiles_directory_excluded_usersfilterint[] $ids
xpac_user_profiles_directory_context_free_filtersfilterstring[] $filters (default [''])
xpac_user_profiles_directory_card_actionsfilterstring $markup, WP_User $user, array $attributes
xpac_user_profiles_privacy_choicesfilterarray $choices (id => title, description, icon)
xpac_user_profiles_privacy_matchfilterbool $match, string $choice, int $ownerId, int $viewerId, string $settingId
xpac_user_profiles_privacy_valuesfilterarray $values, int $userId, string $relation
xpac_user_profiles_user_suspendedactionint $userId, bool $suspended
xpac_user_profiles_incomplete_profile_thresholdfilterint|float $threshold (default 80; 0 or less turns the reminder off)
xpac_forms_admin_form_badgesfilterarray $badges, WP_Post $form
xpac_forms_admin_moved_settings_pagesfilterarray $moved (page name => URL)
xpac_forms_ability_field_typesfilterarray $types (type => block name)
xpac_forms_ability_field_warningsfilterarray $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:

OldNew
xp_cp_avatar_sizesxpac_user_profiles_avatar_sizes
xp_cp_render_profile_dataxpac_user_profiles_render_profile_data
xp_cp_save_profile_fieldsxpac_user_profiles_save_profile_fields
xp_cp_user_profile_fieldsxpac_user_profiles_user_profile_fields
xpac_cp_members_excluded_dynamic_varsxpac_user_profiles_excluded_dynamic_vars
xpac_community_platform_profile_field_savedxpac_user_profiles_profile_field_saved
xpac_cp_allow_admin_accessxpac_user_profiles_allow_admin_access
xp_cp_members_user_redirect_url_on_protected_page_accessxpac_user_profiles_protected_page_redirect

Renamed the same way, deprecated since 1.1.0:

OldNew
xpac_cp_members_query_loop_argsxpac_user_profiles_directory_query_args
xp_cp_excluded_users_in_members_queryxpac_user_profiles_directory_excluded_users
xp_cp_block_visibility_privacy_based_valuesxpac_user_profiles_privacy_values
xp_cp_incomplete_profile_notification_thresholdxpac_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_capability gates Users and Profile fields: the screens, their routes and the AI tools.
  • xpac_user_profiles_admin_boot, _admin_dependencies and _admin_enqueue extend the admin app. The JS filters xpacUserProfiles.admin.groups and .tabs keep their names; the base groups are users and login, and a group added under the old ids profile or sign-in lands in them.
  • xpac_social_login_settings_page fires when the User Profiles screen loads, for people who may set up sign-in, and wp_react_settings_after_module_settings_save on every Social Login save.
  • xpac_forms_user_auth_profile_fields also answers credentials, and xpac_user_auth_form_action also answers for forms whose profile fields fill the account.
  • xpac_user_auth_agent_setup carries account_forms, registration, forms_url and account_pages.
  • Every other xpac_forms_user_auth_*, xpac_user_auth_*, xpac_social_login_* and xpac_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_data to {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_avatar to xpac_user_profiles_avatar, profile completion from xp_cp_profile_completion to xpac_user_profiles_completion, and the files from uploads/xp-cp/avatars/ to uploads/xp-up/avatars/.
  • Onboarding moved from onboarding_complete to xpac_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_profiles first, with xpac_community_platform as 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 profile alias, so pages->profile->user, ->getUrl($user) and ->matchesCurrentPage() work as before. Its addresses carry the user's slug in the xpac_profile query var; xp_cp_member is still read. xpac_user_profiles_displayed_user_id() gives the user it shows, 0 elsewhere, and xpac_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, ->memberOnly and ->onboarding work 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-State header 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_fields gets Core\Profiles as its third argument, with the same methods as Community's data provider, so drop a DataProvider type hint.
  • The xpacCommunityPlatform interactivity state no longer has currentUser.profileData; profile values, and the current user's avatarUrl and displayName, bind to the xpacUserProfiles state. Community keeps its currentUser for 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) and xpac/v1/cp/users-data/export, and the AJAX action xp_cp_export_users, are gone; the xpac/v1/user-profiles/admin/* routes replace them. xp_cp_users_list_table_columns is 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_type returns file.
  • xpac_user_profiles_remove_avatar is gone: User Profiles keeps the photos and removes them itself.
  • Community's Members module is gone: every CommunityPlatform\Modules\Members\* class, including Members\Module::$data. CommunityPlatform\Core\PrivacySettings forwards to Core\Privacy for one release. Privacy choices moved from xpac_community_privacy_settings to xpac_user_profiles_privacy, the left-out users from xp_cp_exclude_admins_in_members_query to xpac_user_profiles_directory_excluded, and the Search page from xpac_community_platform to xpac_user_profiles. The old values stay this release.
  • The directory route is xpac/v1/user-profiles/directory; cp/members still answers this release. JS globals: window.xpacCpUsersQuery is window.xpacUserProfilesUsersQuery, and the privacy block's globals are window.xpacUserProfilesPrivacy and window.xpacUserProfilesPrivacyEditor.
  • personal_bio_visibility is 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."

On this page