SfSkills Domains Docs GitHub

Home / data / person-accounts

person-accounts

Use when enabling, configuring, or troubleshooting Person Accounts in a Salesforce org — includes B2C data model design, IsPersonAccount flag handling, Account-Contact behavior differences, reporting impact, migration planning, and integration requirements. NOT for standard B2B Account/Contact modeling - use data/data-model-design-patterns.

Open the skill folder on GitHub


Person Accounts

This skill activates when a practitioner needs to enable, configure, build on, or troubleshoot Person Accounts — Salesforce's combined Account+Contact model for individual consumer (B2C) records. It covers the data model semantics, API behavior differences, reporting impact, migration considerations, and integration patterns unique to Person Accounts.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

What Person Accounts Are

A Person Account is a single Salesforce record that simultaneously represents both an Account and a Contact for an individual person (a consumer). When you view a Person Account in the UI or via API, the record is stored as an Account sObject. Behind the scenes, Salesforce automatically creates and maintains a shadow Contact record — called the PersonContact — that is linked to the Account record via the PersonContactId field.

The IsPersonAccount Boolean field on the Account sObject distinguishes Person Accounts from Business Accounts. When IsPersonAccount = true, the record is a person account; when false (or absent), it is a business account.

Person Account-specific fields (such as PersonEmail, PersonPhone, PersonBirthdate, PersonMailingCity) are surfaced on the Account object but are actually stored on the underlying PersonContact. These fields map to the standard Contact fields (Email, Phone, Birthdate, MailingCity) on the PersonContact record.

Person Accounts are designed for B2C use cases — retail customers, insurance policyholders, healthcare patients, financial services clients — where the customer is an individual person, not an organization.

Enabling Person Accounts

Enabling Person Accounts is a one-way, permanent operation. Once enabled in an org, it cannot be disabled. This makes the decision consequential for org design.

Prerequisites before contacting Salesforce to enable:

  1. The org must be Enterprise Edition or higher (or a supported industry cloud edition).
  2. All Contacts in the org must have an AccountId — there must be no "private contacts" (Contacts with no parent Account). Run SELECT Id FROM Contact WHERE AccountId = null to verify.
  3. At least one Account Record Type must exist or be created, which will be designated as the Person Account record type.
  4. Review all existing Apex, Flows, integrations, and AppExchange packages for Person Account compatibility.

The actual enablement is performed by Salesforce Support (a support case in production orgs) or via Setup > Account Settings in some sandbox environments. After enablement, at least one Account Record Type must be designated as a Person Account record type in Setup > Account Settings.

After enablement, you cannot go back. If your org has B2B records, those Business Accounts will remain Business Accounts — but you now have both models coexisting.

Data Model and API Behavior

When Person Accounts is enabled:

Record Types and the Person Account Record Type

After enablement, at least one Account Record Type must be designated as a Person Account record type. This designation:

Separate Record Type sets are required for Person Accounts and Business Accounts — fields, picklist values, and page layouts differ significantly between the two models.

Limitations of Person Accounts

LimitationDetail
No child ContactsCannot create a Contact with AccountId pointing to a Person Account. Person Accounts are individuals.
No Contact Roles on Opportunities through PersonContactStandard OCR works, but the PersonContactId (not a new Contact) is used.
AppExchange compatibilityMany packages assume standard Account+Contact structure and don't handle IsPersonAccount = true. Verify before enabling.
Merge behaviorDifferent merge rules than Business Accounts. Person Accounts can only merge with other Person Accounts.
SOQL contact queriesSELECT Id FROM Contact returns PersonContact records mixed with regular Contacts unless filtered.

Reporting Impact

Enabling Person Accounts changes the behavior of Contact-based reports:

Health Cloud and Financial Services Cloud

Health Cloud and Financial Services Cloud (FSC) extensively use Person Accounts to represent individual patients, clients, and policyholders. In these industry clouds:


Common Patterns

Pattern: Checking IsPersonAccount Before Processing in Apex

When to use: Any Apex trigger, batch, or service class that operates on Account records in a mixed B2B+B2C org. Without this check, logic built for Business Accounts will silently execute against Person Accounts and vice versa.

How it works:

trigger AccountTrigger on Account (before insert, before update) {
    for (Account acc : Trigger.new) {
        if (acc.IsPersonAccount) {
            // Person Account-specific logic
            // Use PersonEmail, PersonPhone, PersonBirthdate
            processPersonAccount(acc);
        } else {
            // Business Account logic
            processBusinessAccount(acc);
        }
    }
}

Note: IsPersonAccount is a formula field on Account. In before insert triggers it may not yet be set — check if a Person Account Record Type Id is being assigned instead.

Why not skip the check: Business Account logic often accesses child Contacts (which Person Accounts cannot have), and Person Account logic accesses Person-prefixed fields (which are null on Business Accounts). Mixing the two without branching causes null pointer errors and data corruption.

Pattern: Querying Person Accounts via the Account Object

When to use: When an integration or report needs to retrieve all individual consumers (Person Accounts) from a mixed org.

How it works:

SELECT Id, Name, PersonEmail, PersonPhone, PersonBirthdate, PersonContactId
FROM Account
WHERE IsPersonAccount = true
ORDER BY Name

To also access Contact-model fields through the PersonContact relationship:

SELECT Id, Name, PersonEmail, PersonContact.OtherCity
FROM Account
WHERE IsPersonAccount = true

Why not query Contact: Querying Contact returns PersonContact records mixed with regular Contacts. The Contact record for a Person Account is system-managed and not the canonical record — the Account Id is the canonical identifier.

Pattern: Excluding Person Accounts from B2B Contact Queries

When to use: Existing code or reports that query Contacts and must not include Person Account PersonContact records.

How it works:

SELECT Id, FirstName, LastName, Email, AccountId
FROM Contact
WHERE Account.IsPersonAccount = false

Or in Apex trigger on Contact, skip PersonContact records:

for (Contact c : Trigger.new) {
    if (c.Account.IsPersonAccount) {
        continue; // skip Person Account system contacts
    }
    // standard Contact logic
}

Why this matters: Without this filter, automations that iterate over Contacts will process PersonContact records — which are system-managed and should not be directly modified or deleted by custom logic.


Decision Guidance

SituationRecommended ApproachReason
Org is pure B2C (all customers are individual people)Enable Person Accounts, use Person Account record type for all Account recordsUnified model; all consumer fields on one record
Org is pure B2B (all accounts are organizations)Do not enable Person AccountsNo benefit; adds complexity to reports and code
Org has both organizations and individuals as customersEnable Person Accounts; use separate Account Record Types for Person vs BusinessCoexistence requires strict branching in all code and reports
External system sends one record per person (no separate account)Map to Person Account via Account API; use PersonEmail/PersonPhone fieldsPerson Account is the canonical single-record consumer model
External system sends separate Account and Contact recordsMap to standard Business Account + ContactPerson Accounts do not support child contacts
Org runs Health Cloud or FSCEnable Person Accounts (required or strongly recommended by industry cloud)Industry cloud relationships are built on Person Account model
AppExchange package does not support Person AccountsEvaluate package compatibility before enablement; contact ISV if neededSome packages break when IsPersonAccount = true records exist
Need to report on consumers only (no business accounts)Add Account: Is Person Account = True filter to all relevant reportsWithout this filter, Business Accounts appear in consumer reports
Need to convert existing individual Contacts to Person AccountsPlan a data migration; there is no automatic conversionNo out-of-box tool converts Business Account+Contact pairs to Person Accounts

Step-by-step instructions for an AI agent or practitioner working on Person Accounts:

  1. Confirm prerequisites and scope: Check if Person Accounts is already enabled. If not, run the query SELECT Id FROM Contact WHERE AccountId = null to confirm no private contacts exist. Confirm org edition eligibility. Document whether this is a pure B2C org or a mixed B2B+B2C org.
  2. Assess impact before enablement: Audit all Apex classes, triggers, Flows, and AppExchange packages for Person Account compatibility. Specifically look for code that queries Contacts without an IsPersonAccount filter, or that creates Contacts with a Business Account parent.
  3. Configure Record Types: Ensure at least one Account Record Type is designated (or will be designated) as a Person Account record type. Design separate page layouts for Person Accounts vs Business Accounts.
  4. Request enablement: Open a Salesforce Support case for production orgs, or enable via Setup in sandbox. Verify the IsPersonAccount field appears on Account after enablement.
  5. Update code and reports: Add IsPersonAccount checks to all Apex that processes Account or Contact records. Update Contact-based SOQL queries to filter out PersonContact records where needed. Update reports to add Is Person Account filters.
  6. Test integrations: Run integration tests against sandbox. Confirm external systems correctly set RecordTypeId to a Person Account record type when creating individuals. Confirm IsPersonAccount flag is handled in inbound and outbound payloads.
  7. Validate and document: Run scripts/check_person_accounts.py against exported metadata. Confirm all checklist items pass. Document the B2B/B2C model decision and any integration contract changes.

Review Checklist

Run through these before marking Person Accounts work complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. Person Account enablement is permanent and irreversible — Once enabled, Person Accounts cannot be disabled. If the org later decides the B2C model is not needed, there is no rollback. All related data, record types, and code changes persist. This decision must be made deliberately with full stakeholder alignment.
  2. SOQL on Contact includes PersonContact records — Any existing SELECT ... FROM Contact query will silently include the system-managed PersonContact records for each Person Account. Automations or integrations that process Contact query results will encounter these records and may behave incorrectly — updating, deleting, or re-syncing system-managed records they were not designed to handle.
  3. Person Accounts cannot have child Contacts — A common mistake when migrating a B2C org is trying to link a Contact to a Person Account via AccountId. Salesforce blocks this with an error. Person Accounts represent individual people and do not model an organization with employees.
  4. IsPersonAccount is null (not false) in before insert context — In a before insert trigger on Account, IsPersonAccount has not yet been set by the platform. Do not rely on this field in before insert logic; instead check whether the RecordTypeId being assigned is a Person Account record type.
  5. AppExchange packages silently fail or error on Person Account records — Many older AppExchange packages were built before Person Accounts were common and assume all Accounts have child Contacts. When these packages run actions on Person Accounts, they may throw errors, silently skip records, or corrupt data by creating orphan Contacts attached to Person Accounts (which then fails the platform constraint).
  6. Merging Person Accounts with Business Accounts is blocked — Salesforce only allows merging records of the same type. You cannot merge a Person Account with a Business Account. Duplicate detection rules need to be segmented separately for Person Accounts and Business Accounts to avoid false merge suggestions.

Output Artifacts

ArtifactDescription
person-accounts-template.mdWork template for Person Account enablement or migration projects — captures prerequisites, record type design decisions, Apex impact assessment, and integration changes
check_person_accounts.pystdlib Python checker that scans Salesforce metadata XML for common Person Account issues: Apex classes missing IsPersonAccount checks, Contact SOQL without person account filters

Package files