Developers know that it is not a best practice to hardcode IDs in code, as documented in the Salesforce Developers site.
https://developer.salesforce.com/page/Best_Practice%3A_Avoid_Hardcoding_IDs
It is a big pet peeve of mine when I see hardcoded IDs in formulas, validation rules, process builder, flow, etc. The same best practices apply on the declarative side as with the development side of the house.
The reason why you want to avoid hardcoding Salesforce IDs is that when the new record that your configuration item is referencing is created in a sandbox, and then created in every sandbox leading up and including Production, that new record’s Salesforce ID will not be the same. You will need to update each reference of this hardcoded Salesforce record ID in every sandbox or production. As a result, you have different versions of your formula, validation rule. process builder or flow, etc. in your regions. A maintenance nightmare!
When I see hardcoded IDs and question why, I’m often told things like, “Process builder only takes the ID. There is nothing I can do.” Not true.
Where possible, rather than using the ID, reference it by something that is the same in all regions and less likely to change, such as the API name or field label. If Salesforce will only take the ID, I can offer you three ways you can use to avoid keying in that 15- or 18 character ID into that formula, validation rule, process builder and flow.
On the declarative side, we can use the same configuration tools (aka super powers) that developers use in code, such as Custom Labels, Custom Settings and in some cases, Custom Metadata Types to store Salesforce IDs so they can be managed outside of a formula field, validation rule, process builder, flow, etc.
Let’s get to know each one, when you should use or not use it, how to find, configure it and deploy it. Then, let’s clean up those orgs of hardcoded IDs, ok?!
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 formula fields, validation rules, processes and flows. Think of a custom field is just a custom text field that isn’t object specific. It can be called anywhere in Salesforce. In other words, it is not object or configuration type specific and can therefore be leveraged throughout the org.
This is an example of a custom label:
Provide the Salesforce ID. Here, to play it safe, I provide the 18 character case insensitive ID.
You can categorize a custom label to give you and your admins/developers a clue as to where it is 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?
When you have several situations where you reference IDs. Then it makes sense for you to create an org wide custom settings (think, custom object’s little sister) to store all of your Salesforce ID references in one place.
Where can I find it?
In Classic, Custom Labels is found under Create | Custom Labels. In Lightning, you can find it under User Interface | Custom Labels. When in doubt, use the Quick Find.
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 and click on the Insert button and then Close to add it to the syntax field.
In Process Builder, select the type “Formula,” then select System Variables, select $Label, locate your custom field and click Choose to insert. Then click on “Use this Formula” to check the syntax and then Save it.
In flow, create a Formula resource. Select “System and Global Variables”, find $Label and expand it. Locate your custom label and select it to add it into the syntax box.
How do I deploy it?
Assuming you are using changesets, you will 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 data sets across your org, or distinguish particular users or profiles based on custom criteria.
There are two types of custom settings: hierarchy and list. We are only going to focus on the hierarchy type since the list type custom setting cannot be called from configuration.
For use in formulas, flows, processes and validation rules, we need to use hierarchy custom settings. This custom setting uses built-in hierarchical logic that lets you “personalize” settings for specific profiles or users in addition to organization information.
Note: Similar to records in custom objects, the data in a custom setting is just that, data. This means that 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 is an example of an organization custom setting.
When would I use it?
When you have several situations where you reference IDs in validation rules, formulas or process builder, then it makes sense for you to create an org wide custom settings to store all of your Salesforce ID references in one place.
When would I not?
If you need to reference IDs in flow, you want to use custom metadata type, which is a step up from custom setting. Custom metadata type data records are metadata type, which means they do not get deleted with sandbox refreshes or new sandboxes. You can deploy the data using custom metadata type in changesets.
Where can I find it?
In Classic, Custom Settings is found under Develop | Custom Settings. In Lightning, you can find it under Custom Code | Custom Settings. When in doubt, use the Quick Find to search.
Click the New button. 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 setting type.
Create custom fields for the custom setting. Once done, click on the “Manage” button 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, to play it safe, I 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 on the Insert button and then Close to add it to the syntax field.
In process builder, select the type “Formula,” then select System Variables, select $Setup, locate your custom field and click Choose to insert. Then click on “Use this Formula” to check the syntax and then Save it.
In flow, create a Formula resource. Select “System and Global Variables”, find $Setup and expand it. Locate your custom lsetting field and select it to add it into the syntax box.
How do I deploy it?
Assuming you are using changesets, you will 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 under the Custom Fields component type. These are deployable. You can use data loader or manually create the custom settings data in the sandbox or production post deployment.
What’s a Custom Metadata Type?
Sidebar: I absolutely custom metadata types! They are the bomb! And I can’t wait to see this feature continue to grow with future releases.
Custom metadata is customizable, deployable, packageable, and upgradeable application metadata. First, you create a custom metadata type, 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 custom metadata type has a list of custom fields that represent aspects of the metadata.
The best part is that the data records associated to a custom metadata type 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! This means that like configuration and code, it is deployable via changesets, Dreamfactory’s Snapshot, Eclipse, etc.
Here is an example of a custom metadata type.
Click on the “New” button. Provide the label, plural label and the object name. You can call these whatever you want.
Create custom fields for the custom metadata type. Once done, click on the “Manage” button to create the data records for the custom metadata type.
For the Label and the Name, give it a descriptive name, no spaces. They can be the same as the example below.
Provide the Salesforce ID. Here, to play it safe, I provide the 18 character case insensitive ID.
When would I use it?
If you need to reference IDs in flow, you want to use custom metadata type, which is a step up from custom setting. Custom metadata type data records are metadata type, which means it does not get deleted with sandbox refreshes or new sandboxes. You can deploy the data using custom metadata type in changesets.
When would I not?
If you need to reference IDs in validation rules, formulas or processes as of this blog post. Fingers crossed, hopefully, one day, we can use it in those configuration items too! How about it, Avrom Roy-Faderman, Vladimir Gerasimov and Aaron Slettehaugh?
Where can I find it?
In Classic, Custom Metadata Types is found under Develop | Custom Metadata Types. In Lightning, you can find it under Custom Code | Custom Metadata Types. When in doubt, use the Quick Find to search.
How do I add it?
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 custom metadata type but the data record’s label.
In this example, we are looking up the ID associated with the JenLeeUserID custom metadata type data record.
We will perform a record lookup of the custom metadata type (found under the custom section of the object). Use the Label to lookup the record. Note: This must be an exact match to your custom metadata type data record. If it is not, flow will not find it.
Once the data record found, reference the ID field and store it in the flow variable resource.
Here is an animated gif showing how to configure this in flow.
How do I deploy it?
Assuming you are using changesets, you will find the custom metadata type name listed alphabetically in the component list. When you select the custom metadata type name, you will find the associated data records. From there, click on the “View/Add Dependencies” button, this will identify the custom metadata type itself, custom metadata type page layouts, custom fields, etc. You can select to add all of those components to your changeset.
Now, use your new AwesomeAdmin super powers and prevent hardcoding in your org!
To avoid hard-coding IDs in Process Builder, another approach is to have your process call a Flow to lookup the ID. For instance if a process needs a record type ID, it could call a Flow to lookup the ID based on record type name. Do you think this approach has advantages/disadvantages compared to using custom labels or settings?
LikeLike
Yes, this is the other way to go about it. This post was meant to highlight the use of custom labels, custom settings and custom metadata types. You can only do the lookup in flow but not process builder, validation rules, etc.
LikeLike
Can you tell me now in Spring 17 how many total of master detail and lookup relationship is available? Thank you!
LikeLike
I suggest you post this question out on the success community. Thank you.
LikeLike
Thanks You!- this came in handy today. We have a set of friendly taps on the shoulder to users who create accounts but don’t list themselves as a BD contact (shared record with 5 divisions) and it only applies to one record type.
LikeLike
Glad I was able to be of help
LikeLiked by 1 person
Awesome, awesome post! I’ll be referring to this frequently and passing the link on to friends. Thank you!
LikeLike
Glad you found it helpful. Thank you for sharing with your friends.
LikeLike
Hi,
Thank you for the useful article. However, I am struggling to reference the custom label which value is User ID in Lightning. When I use following syntax I receive an error ” You cannot use a custom label in the ID field”
$Label.c.LabelName.
Please advise. Thank you
LikeLike
I’m not following what you are trying to do. Can you message me via the Success Community or Twitter?
LikeLike
Thank you, this is a great post with very helpful information that is clearly explained in a fun way!
LikeLike
Thank you
LikeLike
I think it is best to take this to the Trailblazer community and not here on this blog. I’m not sure I am following your use case.
LikeLike
As always Jen you are amazing!
LikeLike
Thanks!
LikeLike
Are we able to reference custom metadata types in Workflow Rule criteria?
LikeLike
No and Salesforce is not making any further enhancements to workflow rules either.
LikeLike
Thank you Jen for a great an informative article. Found this at the right time.
LikeLike
Happy to found this helpful.
LikeLike
This article needs to be added to all Salesforce Admins’ list of resources! It’s 3 years old and is still valuable information for configuration. Thanks!
LikeLike
Hi Jenwlee
I followed the same process to update record type. My question is for Value field you given Record type ID.After deployment to QA do we need to hard cod or update same field with updated record type id.when i tried to retrive its showing record type id from dev sandbox.
CaseCustomersuccess
en_US
false
CaseCustomersuccess
0123B00000180Qm
LikeLike
The point of the custom label, custom setting or custom metadata type in putting the id there is so it is not hardcoded where referenced. I noted that if you can creating the thing you are referencing for the first time, that id will not be the same in the next sandbox and including production. The only time the id is the same is if the id is created in production and brought down to the sandbox via sandbox creation or refresh. So, yes, in your case, you will need to update the Id in all sandboxes and production.
LikeLike
Such a great read!
LikeLike
Glad you enjoyed it.
LikeLike