As you build solutions, you often need to reference a component or text, whether it be a record type, permission set, queue, or user. What do you do? The quickest way is to reference the Salesforce ID. One and done. But is it the best way?
A best practice in technology is to not reference IDs or text directly, or “hard code” them. That same best practice applies to the declarative side as well. You should not hard code IDs or text in your formulas, validation rules, processes, flows, and so on.
What’s so bad about hard coding?
But why is it such a bad thing to do? It gets the job done. Here are three reasons why you shouldn’t hard code.
First, the component you need to reference does not exist in Production — you just created it for the solution you’re building. That component will have a new ID that only exists in that sandbox. That same component will need to be created in each sandbox leading up to Production. Each time that component is created, a different Salesforce ID is created and, hence, a different ID will be referenced. As a result, you’ll have different versions of your formula, validation rule, process, flow, and so on in your sandboxes and Production. What a deployment and maintenance nightmare!
Second, let’s say you hard coded messaging that’s displayed in a Flow screen and other components shown to your community or internal users. Marketing decides to update the message. Guess what? Since that same message is hard-coded everywhere it’s shown, you’ll now need to maintain that text in all the places — and that assumes you remember what all those places were.
And third, if you need to troubleshoot or enhance an existing solution and it references a hard-coded ID, you can’t easily tell what that component is without looking up the ID. The Salesforce ID is not self-describing.
Alternatives to hard coding
Where possible, rather than using the ID or hard coding text, reference the component by something that is the same in all sandboxes/Production and is less likely to change, such as the API or developer name. Or, in the case of Flow, you can query with a Get Records using the developer name to find the ID or text. You can possibly use the field label; however, there may be situations where the label changes.
On the declarative side, we can use the same configuration tools (in other words, superpowers) that developers use in code — such as custom metadata types (CMDTs), custom labels, and custom settings — to store Salesforce IDs or text so they can be managed outside of a formula field, validation rule, Process Builder, Flow, and so on.
Let’s get to know each one, when you should use or not use it, and how to find, configure, and deploy it. Then, let’s clean up those orgs of hard-coded IDs and text, okay!?
Before we get into the nitty-gritty of what custom metadata types (or CMDTs) are, we want to note that our recommendation, in terms of the three configuration tools, is to use CMDTs first — they ROCK!
Custom metadata is customizable, deployable, packageable, and upgradeable application metadata. First, you create a CMDT, which defines the form of the application metadata. Then, you build reusable functionality that determines the behavior based on metadata of that type. Similar to a custom object or custom setting, a CMDT has a list of custom fields that represent aspects of the metadata.
The best part is that the data records associated to a CMDT is METADATA! Why is this huge? This means that, like configuration and code, after a sandbox refresh or a sandbox creation, the data records stay from Production! CMDT is deployable via change sets or any metadata API tool.
Here’s an example of how to create a CMDT.
Click New. Provide the Label, Plural Label, and Object Name. You can call these whatever you want. In this example, we’re keeping it generically named so we can hold several CMDT references.
Create custom fields for the CMDT. In this example, we’re creating a generic text field that we can reuse for multiple CMDT records.
Once done, click Manage to create the data records for the CMDT.
For the Label and the Name, give it a descriptive name with no spaces. They can be the same as the example below. Provide the Salesforce ID. Here, we provide the 18-character case-insensitive ID.
When would I use it?
Use it for all the things! You want to use CMDT first over a custom label or custom setting. CMDT data records are metadata type, which means it does not get deleted with sandbox refreshes or new sandboxes. You can deploy the data using CMDT in change sets.
When would I not use it?
To avoid hard-coded ID references in Flow, we recommend you do a Get Records to get the ID using the API or developer name instead of a Get Records to retrieve an ID stored in a CMDT record.
Where can I find it?
In Lightning, you can find it under Custom Code | Custom Metadata Types.
How do I add it?
In validation rules or formulas, select Insert Field > $CustomMetadata ><name of your custom metadata type>, and then find the custom metadata type field. Once found, select the field, click Insert, and then click Close to add it to the syntax field.
In Flow, unlike a custom label or custom setting where you would use the Formula resource, we will instead perform a record lookup of the CMDT using the data record’s label.
In this example, we’re looking up the Account A record type ID CMDT data record.
We’ll perform a record lookup of the CMDT (found under the custom section of the object). Use the Label to look up the record. Note: This must be an exact match to your CMDT data record. If it’s not, Flow will not find it.
Once the data record is found, reference the ID field and store it in the Flow variable resource.
Here’s an animated GIF showing how to configure this in Flow.
In Process Builder, select the type Formula, select System Variables, select $CustomMetadata, locate your custom field, and click Choose to insert. Then, click Use this Formula to check the syntax, and save your changes.
How do I deploy it?
Assuming you’re using change sets, you’ll find the CMDT name listed alphabetically in the component list. When you select the CMDT name, you’ll find the associated data records. From there, click View/Add Dependencies. This will identify the CMDT itself, CMDT page layouts, custom fields, and so on. You can select to add all of those components to your change set.
We’ve given you a taste of CMDTs. Want to learn more? Take it from a Trailhead All Star Ranger — there’s no better place to learn than on Trailhead! Check out the Custom Metadata Type Basics module to learn more about CMDTs in declarative components. CMDTs are a great tool to add to your #AwesomeAdmin toolkit. #KnowledgeIsPower
What’s a custom label?
Traditionally, custom labels enable developers to create multilingual applications by automatically presenting information (for example, help text or error messages) in a user’s native language. Custom labels are custom text values that can be accessed from Apex classes, Visualforce pages, or Lightning components.
However, custom labels can also be used for formula fields, validation rules, processes, and flows. Think of a custom label as a custom text field that isn’t object-specific — it can be called anywhere in Salesforce. In other words, it’s not object- or configuration type-specific and can therefore be leveraged throughout the org.
Here’s an example of a custom label.
Provide the Salesforce ID. To play it safe, in this example, the value contains the 18-character case-insensitive ID.
Admin Tip: You can categorize a custom label to give you and your admins/developers a clue as to where it’s used, since custom labels lack a Description field.
When would I use it?
When you have a few circumstances where you need to reference an ID.
When would I not use it?
When you have several situations where you reference IDs or text. In these cases, it makes sense for you to create a CMDT or custom setting (think, custom object’s little sisters) to store all of your Salesforce ID or text references in one place.
Where can I find it?
In Lightning, you can find it under User Interface | Custom Labels.
How do I add it?
In a validation rule or formula, under Insert Field, find $Label, and then find the custom label by name. Once found, select the field, click Insert, and then click Close to add it to the syntax field.
In Flow, create a Formula resource. In the formula box, locate $Label and expand it. Locate your custom label and select it to add it into the syntax box.
In Process Builder, select the type Formula, select System Variables, select $Label, locate your custom field, and click Choose to insert. Then, click Use this Formula to check the syntax, and save your work.
How do I deploy it?
Assuming you’re using change sets, you’ll find this under Custom Labels. Locate the custom label and add it to your component list.
What’s a custom setting?
Custom settings are similar to custom objects because they let you customize org data. Unlike custom objects which have records based on them, custom settings allow you to utilize custom datasets across your org, or distinguish particular users or profiles based on custom criteria.
Note: Similar to records in custom objects, the data in a custom setting is just that — data. This means you need to export your custom settings before a sandbox refresh so you can load the custom setting data records back into the sandbox post refresh.
Here’s an example of an org custom setting.
When would I use it?
When you have several situations where you reference IDs or text in validation rules, formulas, or processes that are different in a sandbox and Production (that is, URL points to test environment in sandboxes and to production environment in Production), then it may make sense for you to create an org-wide custom setting to store all of your Salesforce ID references in one place.
When would I not use it?
If you need to reference IDs or text in validation rules, formulas, processes, or flows, you want to use CMDTs as your first choice, which is a step up from custom settings. CMDT data records are metadata type, which means they do not get deleted with sandbox refreshes or new sandboxes. Plus, you can deploy the data using CMDT in change sets.
Where can I find it?
In Lightning, you can find it under Custom Code | Custom Settings.
Click New. Provide a label and object name (I usually make it the same). Make sure the Setting Type is Hierarchy. Once created, you can’t switch the setting type.
Create custom fields for the custom setting. Once done, click Manage to create the data records for the custom setting.
Click on the first New button. This will allow you to set the data at the organization level.
Provide the Salesforce ID. Here, we provide the 18-character case-insensitive ID.
How do I add it?
In validation rules or formulas, under Insert Field, find $Setup.<name of your custom setting>, and then find the custom setting field. Once found, select the field, and click Insert and then Close to add it to the syntax field.
In Flow, create a Formula resource. In the formula box, find $Setup and expand it. Locate your custom setting field and select it to add it into the syntax box.
In Process Builder, select the type Formula, select System Variables, select $Setup, locate your custom field, and click Choose to insert. Then, click Use this Formula to check the syntax, and save your work.
How do I deploy it?
Assuming you’re using change sets, you’ll find this under Custom Setting. Locate the custom setting and add it to your component list. Don’t forget to also include the custom setting’s fields. They can be found under the Custom Fields component type and are deployable. You can use Data Loader or manually create the custom settings data in the sandbox or Production post deployment.
Now that you’re equipped with new #AwesomeAdmin superpowers, you can prevent hard coding in your org!
If you want to learn MOAR about CMDTs, Trailhead is your trusty go-to source to learn all the things! Check out these other great resources.
Resources