The great potential of Salesforce is infinite customization. But that’s also how we can get into all sorts of trouble!

I am using some strong language in this post to make a point, not to blame/shame/humiliate anyone who built or inherited Contact Record Types. Heck, I HAVE PERSONALLY DONE THIS! We’re all a work in progress. You’re welcome to prove me wrong (kindly) in the comments.

what is a Record Type?

Google tells us that “a record type is way of grouping records within an Object in Salesforce.”

Thanks, but that definition is absolutely useless. By that logic, we could group by First Letter, any picklist, or any other field or attribute of a record. If you SIMPLY want to “group” records, Record Types are NOT your best friend. In fact, they might cause you more questions than answers.

In my hands on experience, Record Types are a way of manipulating the Salesforce User Experience (what colleagues see when they log in) for specific data scenarios. Record Types allow you to:

  • Configure scenario-driven Classic Page Layouts (including marking fields as required)
  • Assign “Default” Record Types by Profile or User Preferences
  • Configure picklist values to conditionally appear
  • Assign “Paths”
  • Probably other things that I can’t think of right now

limitations of Record Type feature

  • Say goodbye to inline editing in a List View. Once Record Types enter the chat, you can only edit records “inline” if there is a Record Type criterion referenced in your List View Filters. Yep, even if all of your relevant records happen to be the same Record Type anyway.
  • Every time you add a new picklist value, you must add it to each Record Type where it applies. If you find yourself adding it to all record types, you might take that as a hint that you are not using Record Types very effectively.
  • When Record Types are enabled on any object, you automatically add clicks for colleagues because before they get to the data entry screen for a “New Contact,” they first need to select the Contact Record Type. Nope.
  • Record Types make uploading data annoying. There, I said it! There’s not a simple way to assign record types to new records without adding VLOOKUPs in a spreadsheet and copying Record Type Ids ONE AT A TIME from the specific Record Type’s URL. I really really hate this! (One of you, please comment with hack to fix this problem for me).
  • Record Types are by definition single-select only. A record can only be in one “state” at a time. So for any data that you are tracking in Salesforce, think about if the types are mutually exclusive. If they are NOT mutually exclusive (ie someone can be a Donor and a Volunteer… love this for nonprofits!) then Record Types are definitely not the right call for structuring data.

oof … Record Types, Contacts, and what to do instead

Let’s talk about why this is a problem specifically for the type of data associated with Contacts, the original topic that kicked off this rant.

I’ve seen Contacts with Record Types such as:

  • Donor
  • Volunteer
  • Board Member
  • Staff
  • Other

I’ve also seen:

  • Active
  • Inactive

And this is a common one, too:

  • Adult
  • Child
  • Other

I find these challenging all for different reasons. Let’s explore some of them!

  • These attributes may be perfectly valid TYPES of Contacts, but in my opinion, they do not make for good use of the Salesforce-specifc feature of Record Types
  • Contacts ALL REPRESENT PEOPLE and people = people. Ok, I know that is tautological but I think that Record Types are most useful when they represent subcategories of a whole that do not share most attributes in common. When it comes to Contacts, the types of data we typically collect are common across the board… name, pronoun, contact info, preferences, etc. We don’t need a different format for some types of Contacts as for others.
  • Over the course of relationship development, contacts may hit literally ALL of the types listed above and maybe some of them at the same time. Instead of using a narrow structure of “Record Type,” why not use a more sophisticated structure like rollup fields for “number of donations” “number of volunteer shifts” and campaigns/affiliations to show what group connections a contact may have (Board, Staff, Former, etc)
  • I find the Child/Adult dichotomy particularly challenging. Especially if your org also serves teenagers, or serves youth long enough for them to become teenagers. Is there automation in place to update Child records to Adults or Alumni? Also, in NPSP you can remove Contact First Name from Household Naming Convention and mark children as Do Not Contact. Or you can filter by Birth Date! What data do you need to only collect for children that cannot be collected in a Conditional Flow or Quick Action or external registration form?

what to do instead

If you are currently using Record Types and you want to change, hooray! That’s so cool and nothing to be ashamed of. After all, one of my core values is “Change is Possible!” (And if I didn’t think I could influence you to change your Record Types… then why would I be writing this blog post?)

Custom artwork by Katie Blanchard

Ripping out Record Types will take some planning. This is one area where I would unequivocally recommend testing in a Sandbox because you can inadvertently break a lot of stuff when changing something that is so foundational in a database structure.

  1. Create a new Sandbox for your work. Export and backup data that you will be fiddling with.
  2. Think about the data categories that are important to you. If they are not Record Types, what should they be instead? (Hint: usually a combination of fields and related records, like Campaign/Campaign Members, Program/Program Engagements (if you are using PMM), or Affiliations/Relationships (if you. are using NPSP).
  3. Run reports (group by Record Type) to show how popular certain Record Types are. You may quickly notice that some RTs are basically not in use anyway.
  4. Think about the User Experience elements. For example,
    • If you were using RTs for conditional picklist values, consider switching to Dependent Picklists;
    • If you were using RTs for page layouts, consider using Dynamic Forms, Dynamic Lighting Pages, Screen Flows, and Single Related Lists with conditional logic;
    • Make sure all Profiles have access to the new/relevant RT(s) only (particularly important to determine default RT if you are using more than one)
  5. Brainstorm and test downstream effects
    • Flows, Process Builders, or other automation and custom code (check for hard-coded RT ids)
    • Reports and List Views that rely on Record Type filters
    • Form Connectors (ie Form Assembly) or other Integrations
    • Experience Cloud (fka Community Cloud) Page Variations and Audiences
  6. Move Data using an ETL (Extract, Transform, Load) tool of your choice. This will be the result of your new data architecture from step 2.
  7. Communicate with your colleages
    • Make a plan for when you want to make these changes and notify your team in advance!
  8. Deactivate unused RTs. You don’t need to rush to delete them!

when to use Record Types

One example that I find particularly handy is record types within the object of Campaigns such as:

  • Ticketed Event
  • Volunteer Opportunity
  • Peer-to-peer Fundraiser
  • List Email

Each of these “Types” of Campaigns need different fields to show up on the page, or within a set of fields, they may need different values to appear in a drop down menu. For example, if you had a field such as Event Format, you might want options “Cash Envelope” or “Online Giving” to show up for the Peer-to-Peer Fundraiser Record Type, and “Zoom” and “In-Person” to show up for the Ticketed Event Record Type. Same field, different options. There are some situations that certainly call for this approach (but in my experience, they are typically few and far between).

Similarly, you might want dramatically different Fields and Related Lists to show on the individual Campaign record page depending on its Record Type. I pulled images below for an “Email” Record Type and a “Fundraiser” Record Type.

a parting word

If you are struggling with this, you are in good company (moi… at least I think so!). This whole issue is an example of Salesforce technical debt becoming OUR technical debt. However, by working together in community and trying to come up with better methods, I think we can make our databases (and the world) a better place. Who’s with me?

13 thoughts on “the case against Contact Record Types in Salesforce

  1. YES! I’ve also witnessed an org with entirely too many contact record types, I wish I time to volunteer to clean those types of things up.

    I think one thing (that hopefully will change sooner than later) that might hold some orgs back from changing is that dynamic forms aren’t available on mobile (right?). And those pesky compact layouts – record types are the only way to control those right now, I hope that changes soon.

  2. I’m definitely guilty of using Contact record types. (Sometimes I still think it might make sense.)
    But as for your question about how to assign to new records–which I assume you mean you are importing–it’s not nearly as hard as you think. If you’re importing with Apsona you can just make a column with the record type name (no need for the Id) and Apsona will figure it out. I’m also pretty sure you can do this using If you’re using the circa-1999 Dataloader, then yeah, it’s misery. But why are you using that?

  3. Don’t believe in contact record types! A waste of time in most cases. Yay! (I presented a single page at Texas Dreamin’ a few years ago that choose donors, volunteers, clients, or advocates all on the same page. It was pretty leading edge and a little iffy several years ago but not now!) The complexity of the page may not be loved by the page advisor. I haven’t experienced true slowdown by conditional visibility but there may be performance impact.

    I did have to resort to a mobile and a desktop contact page, however. GRRRR… but I’ve been sassy about wanting the teams to do mobile first for some time. It’s just not realistic given their mandates internally.

  4. We use record types in our org for contacts. Given that we have both human and animal contacts that realy is the way to go. Since record types is something added after our instance had been going for a while I use our origianal custom field “Contact is an animal” to stay on top of record type data integrity using flow.

    1. Animals as a Record Type seems like a good use case to me! Thanks for bringing this up 🙂

  5. I don’t use contact record types but I’m a big fan of custom object record types (courses vs certifications for one) and also appreciate opportunity record types.

  6. Agree that Contacts usually should not have record types.

    Unfortunately, at least one ISV imposes record types on Contacts, causing all the problems you noted. 😞

    One small point that can possibly mitigate “you automatically add clicks for colleagues”: in personal Settings, users can opt to use the “Default Record Type” for selected object(s).

  7. Here’s your Developer Console / workbench query. Replace SobjectType with any object’s API Name – this one is for the contact object and will result in the 18digit Id as well as the Name and DeveloperName of the record type. You’re welcome.

    Select Id, Name, DeveloperName FROM RecordType WHERE SObjectType=’Contact’

  8. This post vexed me so much. Not because I think you are wrong, but because I’m right on the verge of “helping” my org by INTRODUCING a new record type for Contacts to solve a problem. They are a recruiting company and have business contacts for companies they are recruiting for, and they also have candidate contacts that they are associating with jobs they want to fill. Seemed like a good use case for having two Contact record types, but now I’m flummoxed. Need to think more on this…. 💭

Leave a Reply