You are currently viewing Splitting SalesForce Person Accounts into Account and Contact

Splitting SalesForce Person Accounts into Account and Contact

Did you know that you can split Salesforce Person Account records into Account and Contact records?  Yea neither did I.  That is until a project came up where I had to convert a few million Person Account records into individual Account and Contact records.

Salesforce developed the concept of a Person Account for those who conduct business with individuals (B2C vs B2B).  A Person Account is denoted by the IsPersonAccount boolean on the Account object which is set when a Person Account record type is assigned to the Account record.  During this assignment, the user will have the ability to designate an existing Contact record to form the mandatory 1:1 relationship or else one will be automatically generated and assigned.  So, why would an organization want to split up a Person Account after going through the very specific process to create it?

My experience, and what seems to be the experience of others during my research, seem to indicate that organizations tend to use Person Accounts without fully understanding their use-case in SalesForce.  It isn’t until much later that they realize they are using a feature that is incorrect for their business and thus it is very inefficient.  When this became apparent for my project, we initially explored the path of exporting all of the data from both objects into SQL Server, making the adjustments to the data for it to reflect true Account and Contact records with relationships, and then pushing it back into SalesForce using DBAmp.

Needless to say, the above procedure was becoming very time-consuming and had a lot of moving parts that had to be considered.  In addition to the time and complexity, there was a further reaching issue of related records across all objects. If we were to export all of the data, delete the existing records, and re-import it in the proper format as new data, every Account and Contact would be generated a new unique GUID by the SalesForce system.  Both standard and custom objects would end up with broken relationships or, as a worst case scenario, would have their data completely deleted as a result of Master-Detail fields.  What originally started out as a data shuffle turned into a large effort and thus we went back to the drawing board to explore modifying the data instead of re-importing it.  So, what was the approach that we took to break this apart?

The Account Process

The first thing that we had to do was determine exactly how Person Account records were stored and related in SalesForce.  I reviewed the SOAP API documentation and determined that the indicators were all read-only (such as the IsPersonAccount flag) that was controlled solely by the record type.  If the Account record and/or Contact record was given a record type flagged Person Account, then it was treated as such.  Step one seemed clear; change all of the record types from Person Account to standard Account and Contact types.  So, I built some logic to keep track of legacy relationships between Account and Contact and, using DBAmp and SQL, I scripted what would be needed to turn an Account record of type Person Account into a normal business Account.

All seemed good and I pushed the data against the SalesForce Bulk API using DBAmp, and at back to wait for it to load.  It wasn’t long before the monitoring page started showing failed records and, eventually, I was at 100% failure rate.  I sarcastically thought great and began to open up the error messages.  It turns out that there are fields on the Account object that become “read-only” if they are specific to Person Account fields.  Things such as First Name and Last Name which, naturally, a business wouldn’t have if the account represented a business and not a person (B2B vs B2C).  I cleaned up my field mappings, remapped data to other standard fields or to custom fields, and pushed again.  The success rate was 100%! We were cooking with fire.

The Contact Process

I then moved onto Contacts.  Thinking that this would be a cakewalk, after all, I had already broken apart the relationship, I shuffled the data, mapped some of the old data I couldn’t use from the Account to the Contact record, and then I “pushed” again.  The failure rate was almost 100%.  Repeat the same process for debugging and it turns out that Contacts had two issues.  One issue is that some of the Accounts did not have broken linkage because they would eventually be deleted, and the other being that the Contact record type was still of a type Person Account.  What to do, what to do.  My solution became quite simple.  For the Accounts that would eventually be deleted, the ones still flagged as a Person Account, I assigned them all a special Account record type that could later be easily filtered and was only viewable to System Administrators.  The next step was to just give Contacts a record type that wasn’t of type Person Account.  I made these quick code changes, pushed two more times, and SUCCESS!  I had managed to break apart the SalesForce Person Account architecture.


So, there you have it.  I wouldn’t say it is the most elegant method for converting records, but since when has SalesForce made anything easy for the developers?  There were a few parts to the puzzle, specifically around when I got started on Contacts, that was not reflective in the SOAP API documentation.   I had to make an assumption that the Contact aspect of a Person Account functioned in the same manner as the Account aspect.  While there were some people out there who have done this before, and some posts at a very high level, there were still some pitfalls that were never taken into consideration.  The largest one that I ran into being the fields that become read-only when the record type is no longer a Person Account type.

Was this article helpful? Do you have feedback or questions?  Myself and my readers would love to hear from you, so post a comment below.