Administrator reviewing structured member profile fields on a widescreen monitor beside a printed intake form

A custom user field is not a decoration. It is a named column on the member: an ID that never changes, a value the member typed or picked, and a handful of switches that decide who can edit it, where it prints, and whether XenForo can search it. Treat it like a paint chip and you end up with twenty free-text boxes nobody reads. Treat it like structured data and you can target a notice, promote a group, filter the member list, and change a template without another add-on.

This is not the permissions primer and it is not the ranks article. Those own access and medals. This one owns the extra facts you collect about a person — region, character name, preferred language, staff-only notes — and the official 2.3 machinery that makes those facts useful.

Official manual: Users → Custom user fields lives under the Users chapter (docs.xenforo.com/manual/users/user-fields). The notebook that indexes the same manuals is thinner than the public page. Use both. Where they disagree, the public manual wins.

What a field actually is

Official wording first. Custom user fields let you define additional information or preferences you want to collect from users. Those values can be displayed with messages or in profiles, used as internal data, or used to change behaviours through template changes.

When you create a field you pick an ID. Official: alphanumeric characters only, and once set it cannot be changed. Advanced work — templates, criteria, exports — refers to that ID. Name it like a column, not a label. region, discord_handle, main_character, preferred_locale will still make sense in two years. field3 will not.

Official then splits every field into one of two categories:

Category What the user does What you store
Text fields Types whatever they like Free-form text. You choose single line, multi line, or rich text, plus validation options
Choice fields Picks from your list Each option is a value (alphanumeric, stored) plus text (shown to humans)

That split is the whole design. A region the member types will never be a clean promotion criterion. A region they pick from eu, na, oc, other will. A Discord handle is text. A “I play on the EU cluster” flag is a choice. Do not invent a third category. The official page does not name every widget in the ACP (stars, date, stars-as-rating). It names the two families and the controls that apply to all of them: how the field is editable and where it is displayed.

The notebook adds two locations the public page also names: values can sit next to posts and on the member profile. The administrator’s edit-user screen loads the same fields. Contact-classified fields appear under Additional contact and “usually take the form of handles or user names.” That is the official home for a Discord, Steam, or Battle.net string — not a random Personal details box.

Where the value lives after save

Three official consumers, in the order you will actually use them.

1. The person, in public. Display-on-profile and display-with-messages. Use the profile for long or private-adjacent facts (timezone, “about my character”). Use the message sidebar for one or two identifiers other members need while they read a post (character name, region chip). More than two chips next to every post is noise. Official does not give you a chip budget. Readers will.

2. The administrator. Users → Search for users, then click a name. Official user-profile chapter: the admin view includes every custom field you defined. Contact fields sit under Additional contact. You can edit them there. The user change log records staff edits of profile data; treat a field that staff regularly correct as a staff-owned field, not a vanity one.

3. Templates. Official advanced example:

{$xf.visitor.Profile.custom_fields.fieldId}

That reads the current visitor. Official note, do not skip it: a different variable is needed for “the user that posted this message.” If you paste the visitor form into message_macros you will print the reader’s region on every post. That is a real class of bug. The field ID in that path is the ID you cannot rename. Change the ID and every template that mentions it dies.

Conditionals around that value are how official docs say you “change behaviours.” A banner that only shows when preferred_locale is pl. A sidebar link that only renders when discord_handle is not empty. A “EU LFG” widget display condition that checks the visitor’s region. You do not need an add-on for those three.

Criteria: the reason the field exists

Official Criteria chapter (docs.xenforo.com/manual/common-concepts/criteria) has a section the notebook claimed was missing: User field criteria.

They sit next to ordinary user criteria (group membership, username contains, message count between). The options adapt to the field type:

  • A text field → Field contains text
  • A multiple-choice field → pick one or more of the options you defined

Those criteria are the same object used by:

  • Users → Search for users
  • Users → Member statistics
  • Communication → Notices
  • Communication → Contact users
  • Groups & permissions → User group promotions (promotions consume the Criteria system)

That list is why a choice field is worth more than a pretty profile. A notice “EU maintenance window Saturday 02:00 UTC” targeted at region = eu. A promotion that adds the Verified Discord secondary group when discord_handle is not empty and message count ≥ 10. A member-stat block “Newest AU members.” A Contact users pass that emails only people who picked wants_digest = yes.

Official promotions reminder, because it will bite you: the hourly User group promotions cron only processes recently-active users. A field change on an account that has not logged in does nothing until they come back. If you need the whole register flipped today, that is Users → Batch update users, which uses the same criteria searcher.

The notebook’s claim that Criteria “only” evaluates avatar, message count, registration duration, and reaction score is incomplete. The public Criteria page documents user-field criteria explicitly. Combined sources: believe the public page.

Data portability and the member list

Official Users chapter:

  • Users → Data portability exports a single user to XML. The export includes username, email, timezone, date of birth, website, location, Signature, About, and the values of all custom user fields.
  • The user-list Export user list CSV is not a full archive. Official: username, email, registration date, “most important data elements.” Do not treat that CSV as a field backup.

If a field matters legally or operationally (age confirmation, parental contact, staff notes you might need after a ban), confirm it appears in the XML you actually export. Official says all custom field values are included. Verify once on a test user before you trust it in an incident.

Searchability: the notebook says administrators can toggle a field so its values join search indexes and filtering menus for “advanced member discovery.” The public user-fields page is shorter and does not name that toggle. Community ACP practice matches the notebook: there is a control for including a field in member search. Turn it on for region and character name. Leave it off for staff-only notes and anything that looks like a phone number.

User fields are not thread fields

Official Forums → Custom thread fields (docs.xenforo.com/manual/forums/thread-fields) is a different object. Same idea (structured extra data, textboxes / radios / checkboxes), different owner.

Custom user field Custom thread field
ACP Users chapter Forums → Custom thread fields
Attached to The member The first post / thread, not replies
Display Profile, message user info, admin Before message, after message, or thread status block (status block repeats on every page)
Scope Global to the account Applicable forums + Editable by user groups (same pattern as prefixes)

A character name that follows the person everywhere is a user field. A “server IP + port” that belongs to one listing thread is a thread field — that is how the server listing article already told you to stop inventing a directory add-on for five columns. A whitelist application’s “character backstory” is a thread field on the application forum, not a profile novel. The whitelist piece owns that workflow.

Resource Manager fields, if you run XFRM, are a third object. Official user-fields and thread-fields pages do not document them. Do not assume the same ID or the same criteria. If you need a download’s Minecraft version, that is a resource field, not a user field.

Eight fields that earn their keep

Build a set. Do not browse the ACP inventing boxes. These eight cover most boards that are not a single-language hobby club.

1. region — choice, shown on profile, searchable

Options with stable values: eu, na, sa, af, as, oc, other. Display text can be “Europe,” “North America,” and so on. Use it for notices (“EU voice chat down”), promotions (“Regional EU” banner group), and a member-stat block. Do not make it required on registration unless the whole community is region-locked. Guests who pick wrong will never correct it.

2. discord_handle — single-line text, contact, optional

Official contact bucket. Show on profile, not next to every post (handles get scraped). The Discord integration article is about OAuth, webhooks, and [8WR]. This field is the fallback when you do not run connected accounts, or the human-readable handle next to a connected account. Validation: keep it short. Do not regex Discord’s current username format as if it will last.

3. preferred_locale — choice, used in templates and notices

Even on a “English only” board, a locale field lets you target a Polish or German notice without installing a second language pack. If you do run multiple languages, this field is not a substitute for Appearance → Languages. Official languages are a separate inheritance tree. The field is a preference you can criteria-match; the language pack is the UI. The multilingual article later in this series owns the pack. The field is how you find “members who want German announcements” before you pay for a translation.

4. main_character — single-line text, shown with messages

Gaming and roleplay boards live or die on “who is this.” One line, shown next to posts, searchable. Do not put the whole character sheet here. Sheets belong on a thread or an application. If you need class / faction / server, those are choice fields (faction, home_server) so you can filter. Free-text class names will be “mage,” “Mage,” “frost mage,” and “Frost Mage (alt).”

5. playstyle — choice, profile only

pve, pvp, roleplay, casual, trader. Promotion to a “Looking for group” group, or a notice that only PvP players see the arena event. Keep the list short. Ten playstyles is a form people skip.

6. staff_notes — multi-line text, admin-only, never public, never searchable

Official: fields can be “internal data.” Use that. This is the “spoke to them about the 12 May incident, see warning #4” box that must not appear on the profile, must not appear next to posts, and must not join member search. If the ACP lets you hide a field from the owner, hide it. If it does not, do not put anything here you would not say on a staff forum. The moderation article owns the warning system. This field is the one-line memory that warnings do not store.

7. heard_about — choice, registration, not shown in public

search, youtube, friend, discord, reddit, other. Required on registration if you actually read it. Member statistics and an occasional Contact users pass are the payoff. Do not display it on the profile. Nobody needs to advertise that they came from a raid-recruitment video.

8. accepts_digest — choice yes/no, preferences

Official email chapter is about transport (PHP mail, SMTP, Google OAuth), not about a digest preference field. If you send a weekly staff-written digest via Contact users, you need a criterion. A yes/no field is that criterion. Do not invent a newsletter add-on for a monthly email until this field has a thousand yeses.

What not to put in a field

Permissions. A “is VIP” checkbox that you then read in a template to show a forum is a toy. VIP is a secondary group, usually from a user upgrade or a promotion. Templates that check groups survive; templates that check a field someone can edit do not.

The password, the email, the 2FA state. Official user security: passwords are one-way hashes, 2FA lives under Setup → Service providers → Two-step verification, and staff mandate 2FA with Require two-step verification on the Moderating and Administrative groups. None of that is a custom field.

A second username. Official already has username, custom title, and the title ladder. A “forum nickname” field next to the real username is how you moderate two identities.

Anything you will need to sort numerically unless you are willing to live with text sort. Message counts and dates already exist as user criteria. Do not duplicate them.

PII you cannot defend. A phone number, a real name, a school, a home city more precise than a region. Official XML export will carry it. GDPR-shaped deletion requests will ask for it. If you do not have a process, do not have the field.

Registration versus later

Official user-fields page does not document a “show on registration” toggle in the public prose. The ACP has display / editability controls; community practice is to keep registration to two or three fields that change a decision you make that day (region, heard_about, maybe main_character on a roleplay board). Everything else is a profile prompt after the first login.

Required-on-registration fields raise bounce. A 400-word backstory box on the register form is how you lose the people the engagement article is trying to keep. Put the novel on the whitelist thread.

Editability: a field staff must trust (region used for a private node via promotion) should not be freely editable the day after a ban evasion. Official does not publish a “lock after 7 days” switch. Operational pattern: start editable, and if the value becomes a permission input, move the permission to a group and leave the field as display.

Templates without painting yourself into a merge

Official style and template chapters: customizations live in the child style and become Appearance → Outdated templates on upgrade. A one-line conditional in message_macros or member_view is a customization you will merge. Prefer:

  1. Display location switches on the field itself (profile / message user info) before you touch a template.
  2. Notices with user-field criteria before you write a banner template.
  3. Widget display conditions that read the visitor field, not a forked widget template.
  4. A tiny conditional in a child style, never in Default style, with a comment that names the field ID.

If you need the same field in five templates, you are past “a field” and into an add-on. Official developer docs exist for that. This article stops at the visitor/profile value.

A worked notice and a worked promotion

Notice. Communication → Notices → Add notice. Title: EU Saturday maintenance. Type: floating or scrolling, whatever you already standardized in the news article. Criteria: user field region is eu. Page criteria: only if you want it on / and not inside conversations. Dismissible. One week. That is the entire feature. No template.

Promotion. Groups & permissions → User group promotions → Add promotion. Title: Has Discord on file. Add secondary group Discord listed (a group whose only job is a small banner or a staff search filter — do not put permissions on it). Criteria: discord_handle contains @ or, if you use new-style Discord names, “field is not empty,” plus message count between 5 and -1. Official: empty criteria means the promotion is never awarded automatically. Official: disabling the promotion does not demote people already in the group. Undo path is in the ranks article and the official promotions chapter (change criteria so nobody matches, or batch-update the group off).

Do not use a promotion to grant View node on a paid forum. That is a user upgrade. A field is a fact. A group is a role. An upgrade is a receipt.

Checklist before you add field nine

  • The ID is a stable machine name you would type in a template.
  • It is a choice if you will ever criteria-match it.
  • You know whether it is public, profile-only, contact, or staff-internal.
  • It is not a permission, not a second username, not a duplicate of Location / Website / About.
  • Registration only asks for it if you will read the answer this week.
  • Member search is on only if the value is meant to be found.
  • A test user’s XML export contains it.
  • Analyze permissions still makes sense — the field did not become a back-door role.
  • You can name the notice, promotion, template, or staff workflow that will consume it. If you cannot, delete the draft field.

What this is not

It is not a catalogue of every input widget the ACP might show. Official public docs name text versus choice, editability, display, the visitor template path, criteria, and XML export. They do not, in the pages cited here, walk through stars, date pickers, or HTML wrappers. If your ACP shows those, they are extra controls on the same two families — not a reason to invent a third product.

It is not a roleplay character database. The next article is how to structure a gaming or roleplay board (nodes, applications, listings). Fields are one shelf in that cupboard.

Takeaways

  • Official custom user fields are an ID, a text or choice value, and switches for edit and display.
  • Choice values plus user field criteria are how notices, promotions, member stats, and Contact users become precise.
  • {$xf.visitor.Profile.custom_fields.fieldId} is the current visitor. The poster is a different variable.
  • Thread fields belong to the first post of a thread. Do not store a listing’s IP on the member.
  • Eight named fields cover almost every serious board. Field nine needs a consumer.
  • Internal data is a first-class official use. Staff notes do not go on the profile.
  • XML portability includes every custom field. The member-list CSV does not.

Collect facts you will search. Everything else is a profile prompt you can add after people stay.