SfSkills Domains Docs GitHub

Home / data / community-user-data-migration

community-user-data-migration

Use to migrate external community/portal user accounts at scale — bulk user creation via Data Loader, license-type moves (Customer Community to Customer Community Plus, or to Partner Community), Customer Portal imports, and Contact/Account hierarchy prerequisites.

Open the skill folder on GitHub


Community User Data Migration

Use this skill when bulk-creating or migrating external Experience Cloud / portal user accounts, including moving users between license types and resolving Contact/Account hierarchy requirements. This skill covers the full Data Loader workflow, NetworkMember record management, and profile-to-network association validation.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

Contact/Account Hierarchy as Prerequisite

Every external (portal/community) user in Salesforce is linked to either a Contact or a Person Account. This linkage is enforced at the database level: a User record with UserType of PowerCustomerSuccess, PowerPartner, CustomerSuccess, or CspLitePortal requires a valid ContactId (or, for Person Accounts, an AccountId on the person account). Attempting a bulk User insert without pre-populated Contacts results in an INVALID_CROSS_REFERENCE_KEY or FIELD_INTEGRITY_EXCEPTION error on every row.

Migration sequence must therefore be: Contact/Account upsert first → User insert second. Do not attempt to create Users and Contacts in the same Data Loader job.

NetworkMember Auto-Creation

When a User is assigned a Profile that is associated with an Experience Cloud network (site), Salesforce automatically creates a NetworkMember junction record linking the User to that Network. This auto-creation happens on User insert or on Profile update — it is not a separate step.

However, the inverse is not automatic: when a User's Profile is changed to one associated with a different network (license migration scenario), the old NetworkMember record for the previous network is not automatically deleted. The user will effectively be a member of both the old and new networks until the stale record is cleaned up.

License Migration via Profile Update

Migrating a user from Customer Community to Customer Community Plus (or to Partner Community) is accomplished by updating the ProfileId field on the User record to a Profile associated with the destination license type and site. The license type consumed by a user is determined by the profile, not by a separate license assignment field.

Key constraint: the destination Profile must be explicitly associated with the destination Experience Cloud site in Setup > Digital Experiences > [Site] > Administration > Members. A profile that has community-user license features enabled but is not associated with the target network will not grant site access.

Data Loader Field Mapping for External Users

When inserting Users via Data Loader:


Common Patterns

Pattern: Bulk External User Insert via Data Loader with Pre-Staged Contacts

When to use: Migrating a large volume of net-new external users (Customer Portal, legacy community, or external IdP) into Experience Cloud from a source system export.

How it works:

  1. Export source user data including email, name, and the external identifier that maps to a Contact record.
  2. In the destination org, upsert Contacts using an External ID field (e.g., Legacy_Customer_ID__c) to establish the Contact hierarchy. Confirm row counts match.
  3. Query SELECT Id, Legacy_Customer_ID__c FROM Contact to produce a ContactId lookup map.
  4. Build the User CSV: map ContactId, ProfileId (query by name), UserType, Username, Email, FirstName, LastName, Alias, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, LanguageLocaleKey.
  5. Insert Users via Data Loader. Review error log — INVALID_CROSS_REFERENCE_KEY on ContactId means the Contact lookup failed; recheck External ID mapping.
  6. Verify NetworkMember auto-creation: SELECT Id, MemberId, NetworkId FROM NetworkMember WHERE MemberId IN (:insertedUserIds).

Why not the alternative: Creating Users and Contacts in the same job is not supported by the platform. Apex-based bulk creation in a trigger is possible but reintroduces governor limit risk on very large volumes; Data Loader with staged Contacts is more reliable and auditable.

Pattern: License Type Migration (Profile Update)

When to use: Moving existing users from Customer Community to Customer Community Plus, or from Customer Community Plus to Partner Community, within the same org.

How it works:

  1. Query target users: SELECT Id, ProfileId, Profile.Name FROM User WHERE Profile.Name = 'Customer Community Login User' AND IsActive = true.
  2. Identify the destination Profile name and confirm it is associated with the target network in Setup.
  3. Export User IDs and map to destination ProfileId.
  4. Update ProfileId field via Data Loader update operation.
  5. Post-update: query NetworkMember for old network to identify stale records.
  6. Delete stale NetworkMember records for the old network: SELECT Id FROM NetworkMember WHERE NetworkId = :oldNetworkId AND MemberId IN (:migratedUserIds).

Why not the alternative: Attempting to change UserType directly is not supported after User creation. License migration must be done through Profile reassignment.


Decision Guidance

SituationRecommended ApproachReason
Bulk new external users, Contacts existData Loader User insert with ContactId mappingMost reliable for large volumes; auditable error log
Bulk new external users, no ContactsStage Contact upsert first, then User insertPlatform enforces Contact prerequisite; cannot bypass
License type change (same org)Data Loader Profile update on existing UsersUserType is immutable post-creation; Profile drives license
Person Account orgMap User to AccountId of person account, not ContactIdPerson Account users use different field linkage
Single-site to multi-site migrationUpdate Profile to multi-site profile, clean old NetworkMemberNetworkMember is not auto-cleaned on Profile change
Sandbox-to-production promotionExport Users from sandbox, re-stage Contacts in prod, re-insertUser records cannot be promoted via Change Sets or Metadata API

Step-by-step instructions for an AI agent or practitioner working on this task:

  1. Validate Contact/Account hierarchy — Before touching any User records, query the destination org to confirm every source user maps to an existing Contact (or Person Account). Export SELECT Id, ExternalId__c FROM Contact and cross-reference against the source user list. Resolve all missing Contacts before proceeding.
  2. Confirm profile-to-network association — In Setup > Digital Experiences > [Site] > Administration > Members, verify the target profile appears in the "Selected Profiles" list. Query SELECT Id, Name FROM Profile WHERE Id IN (SELECT ProfileId FROM NetworkMember WHERE NetworkId = :targetNetworkId) as a programmatic check.
  3. Prepare and validate the User CSV — Build the migration CSV with required fields (ContactId, ProfileId, UserType, Username, Email, Alias, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, LanguageLocaleKey, IsActive). Run a pre-flight check: confirm no duplicate Usernames, all ContactIds resolve, all ProfileIds resolve.
  4. Execute Data Loader insert/update — Use insert for new users; use update for license migration (Profile change only). Process in batches of no more than 200 rows per job to keep error logs manageable. Capture the success and error CSVs.
  5. Verify NetworkMember records — After insert, query SELECT Id, MemberId, NetworkId FROM NetworkMember WHERE MemberId IN (:insertedOrUpdatedUserIds) to confirm membership was auto-created for the correct network. For license migrations, also query the old network and delete stale NetworkMember records.
  6. Post-migration validation and cleanup — Confirm user count in destination matches expected count. Deactivate source users (if same org migration) or document deactivation window. Validate that deactivated users are removed from the license count after the grace period. Run smoke tests: log in as a migrated user in a sandbox before production cutover.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. User insert fails silently on ContactId mismatch — If the ContactId in the CSV references a Contact in a different org or a deleted Contact, Data Loader returns INVALID_CROSS_REFERENCE_KEY with no indication of which field is at fault. Always pre-validate ContactIds with a SOQL query before the insert job.
  2. NetworkMember records not auto-cleaned on Profile change — When a User's Profile is updated to one associated with a different network, Salesforce creates a new NetworkMember for the new network but does not remove the old one. The user remains a member of both networks. This causes unexpected portal access and inflated member counts on the old site.
  3. Deactivated users still occupy license seats during migration window — Deactivating a User does not immediately release the license. License seat counts are recalculated on a platform schedule. Plan migration windows to account for this lag; do not assume the freed seats are available the moment you deactivate the old cohort.
  4. UserType is immutable after User creation — You cannot change a User's UserType after the record is created. License migration must be done via Profile reassignment, not by updating UserType. Attempts to update UserType via Apex or the API will throw FIELD_INTEGRITY_EXCEPTION.
  5. Sandbox username collision blocks migration testing — Salesforce appends .invalid or a sandbox suffix to usernames when a sandbox is refreshed. If you export Users from a sandbox and attempt to re-insert without adjusting the Username field, the insert will fail on uniqueness constraints in the destination org.

Output Artifacts

ArtifactDescription
Migration CSV (Users)Validated Data Loader input file with all required User fields
Contact pre-staging CSVUpsert file for establishing Contact/Account hierarchy before User insert
NetworkMember cleanup queriesSOQL to identify and delete stale NetworkMember records post-migration
Post-migration validation queriesSOQL set to confirm User counts, NetworkMember records, and Profile assignments
Migration runbookStep-by-step execution plan with rollback notes (see templates/)

Dependencies

Package files