Salesforce App specific showing tabs to profile users
•21 min read

Understanding Salesforce App Visibility
Each Lightning App (built using Lightning App Builder) can have:
- Navigation Items (Tabs) assigned
- Profiles assigned (to control who sees the app)
However, tab visibility within the app is controlled by:
- App Navigation settings (which tabs are in the app)
- Profile tab visibility (Default On / Default Off / Hidden)
- Permission Sets (can override Profile restrictions)
🏗️ Step-by-Step Setup (Manual way)
✅ Step 1: Create or Open Lightning App
- Go to Setup → App Manager
- Click Edit next to your app (e.g., “Sales App”)
- Under Navigation Items, select the tabs you want included.
✅ Step 2: Assign Profiles to App
- Still in the App setup page, go to User Profiles
- Select only the profiles who should access this app.
✅ Step 3: Control Tab Visibility (via Profiles)
- Go to Setup → Profiles → [Your Profile]
- Under Tab Settings, set:
- Default On for tabs to show by default
- Hidden for tabs you want to hide
⚡ Tip: This combination lets you make a tab visible only in one app and hidden elsewhere.
💻 Automating with Apex / Metadata API
You cannot directly modify app-level tabs via Apex (it’s metadata).
But you can automate profile-tab visibility via the Metadata API using Apex + Tooling API or Deployments.
Here’s an Apex example using Tooling API to update tab visibility:
🧠 Apex Example – Change Tab Visibility for a Profile
// Apex to change tab visibility for a specific profile
public class UpdateTabVisibility {
public static void updateTabVisibility(String profileName, String tabName, String visibility) {
// visibility can be 'DefaultOn', 'DefaultOff', or 'Hidden'
Profile prof = [SELECT Id, Name FROM Profile WHERE Name = :profileName LIMIT 1];
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
MetadataService.Profile profileMD =
(MetadataService.Profile) service.readMetadata('Profile', new String[] { prof.Name }).getRecords()[0];
// Update tab setting
MetadataService.ProfileTabVisibility tabSetting = new MetadataService.ProfileTabVisibility();
tabSetting.tab = tabName;
tabSetting.visibility = visibility;
profileMD.tabVisibilities = new List<MetadataService.ProfileTabVisibility>{tabSetting};
// Deploy the update
List<MetadataService.SaveResult> results = service.updateMetadata(new MetadataService.Metadata[] { profileMD });
if (results[0].success) {
System.debug('Tab visibility updated successfully for ' + profileName);
} else {
System.debug('Error: ' + results[0].errors[0].message);
}
}
}
JavaScript⚠️ This example assumes you’ve added the MetadataService.cls (standard Salesforce metadata wrapper class) to your org.
🧰 Alternate (Simpler) Option — Use Permission Sets
Instead of editing profiles:
- Create a Permission Set with the tab visibility you want.
- Assign it to users of the specific app (or automatically via Apex trigger when they log in or when app assignment changes).
Example: Apex to assign Permission Set
public class AssignAppTabPermission {
public static void assignPermissionSet(Id userId, String permissionSetName) {
PermissionSet ps = [SELECT Id FROM PermissionSet WHERE Name = :permissionSetName LIMIT 1];
if (ps != null) {
PermissionSetAssignment psa = new PermissionSetAssignment(
AssigneeId = userId,
PermissionSetId = ps.Id
);
insert psa;
}
}
}
JavaScript🧩 Summary
| Approach | Where Used | Notes |
|---|---|---|
| App Manager UI | App-specific control | Quick setup; profile assignment supported |
| Profile Tab Settings | Global per tab | Combine with app restriction for control |
| Permission Sets | User-level control | Flexible and can be automated |
| Apex/Metadata API | For automation | Use MetadataService for programmatic control |
Related Posts

How to Automatically create a follow-up Task when a Lead is converted

How You need to update a related child record whenever a parent record’s status changes, but only if the status is “Closed Won.” How would you design this in Apex?
