Mastering the Salesforce Advanced Configurator: A Deep Dive Tutorial

Photo of author
Written By Jean-Michel Tremblay
Salesforce Consultant

Welcome to The Cloud Update! Today, we’re taking a comprehensive look at the Salesforce Advanced Configurator. If you’re looking to manage complex product configurations and enforce sophisticated business logic directly within Salesforce Revenue Cloud, you’re in the right place.

This tutorial will guide you through creating a Constraint Model (CML) from scratch, exploring various rule types, and demonstrating how they come alive in a real-world scenario using a “Robot Bundle” example.

Let’s unlock the power of the Advanced Configurator to build the precise quoting experience your business needs!

Getting Started: Setting the Stage

Before we dive in, this tutorial assumes you have a foundational understanding of Salesforce and Revenue Cloud concepts, including product bundles and attributes. Our main goal is to show you how to use the Advanced Configurator to bring dynamic logic to these existing structures.

We’ll cover:

  • Creating and structuring a new Constraint Model (CML).
  • Bringing in your product’s attributes and options.
  • Implementing a wide array of rule types to control configuration behavior.

Step 1: Creating Your Constraint Model in Salesforce

The journey begins by setting up a new constraint in your Salesforce environment.

  1. Navigate to Constraints: In Salesforce, find and open the “Constraints” object.
  2. Create a New Constraint:
    • Give your constraint a descriptive Name (e.g., “Robot CML”). The API name will likely auto-fill.
    • Set the Usage Type to “Constraint.”
    • For Context Definition, ensure you select the active pricing context definition in your environment (e.g., “Pricing Transaction CD One”).
    • Save your new constraint.
  3. Open the Constraint Builder: Once saved, a constraint version will be created. Click on this version to open the Constraint Builder. This is where the magic happens – where you’ll define your model and rules. Initially, it will be an empty canvas.

Step 2: Structuring Your Model in the Constraint Builder

With the Constraint Builder open, our first task is to lay the groundwork for our product.

  1. Create a New Type: This “Type” represents your main product bundle.
    • Click “New Type.”
    • Name it after your bundle (e.g., “RobotBundle”).
    • Click “Create.” This establishes the parent container for your bundle’s logic.
  2. Define Type Variables (Attributes): Now, let’s bring in the attributes associated with your product.
    • Select your newly created Type (e.g., “RobotBundle”) from the list on the left.
    • At the bottom, click “Define Type Variables.”
    • You can manually create variables, but the powerful option is to Auto generate variables based on Product Catalog Management (PCM).
      • Look up and select your product bundle.
      • The system will pull in all attributes already defined for that bundle in Salesforce.
      • Select the attributes you want to include and save. Your Type will now list these attributes. Default values from PCM will be respected, though you can set defaults here (PCM usually takes precedence).
  3. Define Relationships (Product Options/Components): Next, we add the selectable product options or components within your bundle.
    • With your main Type still selected, switch from the “Variables” tab at the bottom to “Relationships.”
    • Click “Define Relationships.”
    • Again, you can leverage the Auto generate them from PCM option.
      • Select “Product Catalog Management” as the reference library.
      • Look up and select your product bundle.
      • All available product options for that bundle will appear. Select those you need and save.
      • This creates relations under your main Type and also defines individual types for each option further down the list. The example code already lists these relations and individual types.
  4. Define Type Association: The final structural step is to link your CML model directly to the Salesforce product record.
    • Ensure your main Type (e.g., “RobotBundle”) is selected.
    • Switch to the “Associations” tab at the bottom.
    • Click “Define a type association.”
      • For Object Entity, select “Product.”
      • For Object to Map, look up and select your actual product bundle record (e.g., the “Advanced Delivery Robot Bundle”).
      • Save this association.
  5. Save Your Model: At this point, you have the basic structure of your constraint model. Click the main “Save” button in the Constraint Builder.

Important: Remember to Deactivate your model before making CML changes and Activate it to test your rules. The Constraint Builder UI helps with the initial setup, but the detailed rules are often written directly in the CML editor accessible within the constraint version record.

Here’s a look at the structural part of our example CML, defining the RobotBundle type and its attributes/relations, along with the types for related components:

type RobotBundle { @(defaultValue = “Tracked”) string MobilityType = [“Wheeled”, “Tracked”, “Legged”]; @(defaultValue = “Semi-Autonomous”) string Operating_Mode = [“Semi-Autonomous”, “Fully Autonomous”]; string TerrainAdaptationLevel = [“Medium”, “Low”, “Heavy”]; string Payload_Capacity_Requirement = [“Light”, “Medium”, “Heavy”]; int MaxPayload; relation heavydutyroboticarm : HeavyDutyRoboticArm; relation standardroboticarm : StandardRoboticArm; relation wifimodule : WiFiModule; relation fivegmodule : FiveGModule; relation fourgmodule : FourGModule; relation basicsafetykit : BasicSafetyKit; relation advancedsafetykit : AdvancedSafetyKit; relation emergencystop : EmergencyStop; relation leggedbase : LeggedBase; relation wheeledbase : WheeledBase; relation trackedbase : TrackedBase; relation basicsensorsuite : BasicSensorSuite; relation advancedsensorsuite : AdvancedSensorSuite; // Rules will be added here } type HeavyDutyRoboticArm; type StandardRoboticArm; type WiFiModule; type FiveGModule; type FourGModule; type BasicSafetyKit; type AdvancedSafetyKit; type EmergencyStop; type LeggedBase; type WheeledBase; type TrackedBase; type BasicSensorSuite; type AdvancedSensorSuite; // Types for Transaction Scope rules type Warranty; type ExtWarranty;

Step 3: Implementing Configuration Rules – The Core Logic

This is where you bring your product configuration to life. We’ll walk through various rule types using the provided CML code.

Rule Type 1: Basic Constraint Table

Rule Type 1: Basic Constraint Table

  • Purpose: Enforces direct, static relationships between two or more attributes. Think of it as a lookup table for valid combinations. If a selected combination isn’t in the table, the constraint fails, and an error message is typically shown.
  • Example:
    The “Payload_Capacity_Requirement” must directly correspond to a specific “TerrainAdaptationLevel” as defined in the table:
    • “Light” payload requires “Low” terrain adaptation.
    • “Medium” payload requires “Medium” terrain adaptation.
    • “Heavy” payload requires “Heavy” terrain adaptation.
  • CML Code (inside RobotBundle Type):
    constraint(table(Payload_Capacity_Requirement, TerrainAdaptationLevel,
                 {"Light", "Low"},
                 {"Medium", "Medium"},
                 {"Heavy", "Heavy"}),
               "Payload Capacity Requirement must match Terrain Adaptation Level");
  • Testing:
    • When you configure the bundle, selecting “Light” for Payload_Capacity_Requirement will necessitate that TerrainAdaptationLevel is “Low.” If you attempt to set TerrainAdaptationLevel to “Medium” or “Heavy” while Payload_Capacity_Requirement is “Light”, the constraint will fail, and the message “Payload Capacity Requirement must match Terrain Adaptation Level” will be displayed, preventing an invalid configuration. The configurator might also auto-set the corresponding value if the UI is designed to do so based on the first selection.

Rule Type 2: Require Rule

  • Purpose: Ensures that if one condition is met (an attribute is a certain value, or a product option is selected), another product option or attribute value is automatically selected or set.
  • Example (Chained Requirement):
    1. If “Operating Mode” attribute is “Fully Autonomous,” then the “BasicSafetyKit” product option must be selected.
    2. If “BasicSafetyKit” is selected, then the “EmergencyStop” product option must also be selected.
  • CML Code (inside RobotBundle Type):


    require(Operating_Mode == "Fully Autonomous", basicsafetykit[BasicSafetyKit], "Fully Autonomous mode requires the Basic Safety Kit.");
    require(basicsafetykit[BasicSafetyKit], emergencystop[EmergencyStop], "Basic Safety Kit requires an Emergency Stop button.");


  • Testing:
    • Setting “Operating_Mode” to “Fully Autonomous” will automatically check the “BasicSafetyKit.”
    • Because the “BasicSafetyKit” is now checked, the “EmergencyStop” button will also be automatically checked.

Rule Type 3: Preference Rule

  • Purpose: Similar to a “Require” rule, it suggests a selection or value based on another choice. However, the user can override this suggestion.
  • Example: If “Payload_Capacity_Requirement” is “Heavy,” then “TerrainAdaptationLevel” should preferably be “Heavy.”
  • CML Code (inside RobotBundle Type):


    preference(Payload_Capacity_Requirement == "Heavy" -> TerrainAdaptationLevel == "Heavy", "Heavy Payload typically requires Heavy Terrain Adaptation.");


  • Testing: When “Payload_Capacity_Requirement” is set to “Heavy,” “TerrainAdaptationLevel” will automatically switch to “Heavy.” However, the user can then manually change “TerrainAdaptationLevel” to “Low” or “Medium.” An informational message (provided in the rule) will appear if they do.

Rule Type 4: Exclude Rule

  • Purpose: Prevents a specific product option from being selected if a certain condition is met.
  • Example: If “MobilityType” attribute is “Wheeled,” then the “TrackedBase” product option should be excluded (not selectable).
  • CML Code (inside RobotBundle Type):


    exclude(MobilityType == "Wheeled", trackedbase[TrackedBase], "Wheeled mobility excludes the Tracked Base component.");


  • Testing: Given the default for “MobilityType” is “Tracked,” “TrackedBase” is initially available. Changing “MobilityType” to “Wheeled” will cause the “TrackedBase” option to disappear or become unselectable.

Rule Type 5: Conditional Constraint

  • Purpose: Enforces a more complex condition, often involving comparisons or calculations, typically on numerical attributes, based on another attribute’s selection.
  • Example: If “TerrainAdaptationLevel” attribute is “Heavy,” then the “MaxPayload” (a number attribute) must be greater than 1000.
  • CML Code (inside RobotBundle Type):


    constraint(TerrainAdaptationLevel == "Heavy" -> MaxPayload > 1000, "Heavy terrain adaptation requires MaxPayload > 1000.");


  • Testing: If “TerrainAdaptationLevel” is set to “Heavy,” and the user enters “950” for “MaxPayload,” an error message will appear, and they won’t be able to save the configuration until “MaxPayload” is a value greater than 1000.

Rule Type 6: Message Rule

  • Purpose: Displays a message to the user during configuration based on specific conditions. Messages can be informational, warnings, or errors.
  • Example (Warning): If “MobilityType” is “Legged” AND “TerrainAdaptationLevel” is “Low,” display a warning message.
  • CML Code (inside RobotBundle Type):


    message(MobilityType == "Legged" && TerrainAdaptationLevel == "Low", "Warning: Legged mobility might be unstable on Low adaptation terrain.", "Warning");


  • Testing: When both conditions are met, the specified warning message appears. The user can save the configuration but might be blocked from generating an order from this quote until the warning condition is resolved (depending on Salesforce setup).

Rule Type 7: Hide & Disable Rules (Dynamic UI)

  • Purpose: Dynamically control the visibility and editability of attributes or product options based on other field values, including fields on the quote header or quote line.
  • Setup (External Variable – Top of CML file):

    @(contextPath = "SalesTransaction.HideAndDisable")
    extern boolean HideAndDisable;
  • Within RobotBundle

        rule(HideAndDisable == true, "hide", "relation", "wheeledbase", "type", "WheeledBase");

        rule(HideAndDisable == true, "disable", "relation", "advancedsensorsuite", "type", "AdvancedSensorSuite");

        rule(HideAndDisable == true, "hide", "attribute", "Operating_Mode", "value", ["Semi-Autonomous"]);

        rule(HideAndDisable == true, "disable", "attribute", "MaxPayload");

  • Testing:
    • Create a checkbox field (e.g., HideAndDisable__c or ensure HideAndDisable exists) on your Quote object (SalesTransaction).
    • In the configurator:
      • When the checkbox is FALSE on the quote, all options/attributes are visible/editable as per other rules.
      • If you were to add the example hide/disable rules: When the checkbox is TRUE, the corresponding UI elements would be hidden or disabled.

Rule Type 8: Transaction Scope Rules (Auto-adding Products)

  • Purpose: Perform actions at the quote level, such as automatically adding related products (e.g., warranties) to the entire quote based on the presence or specific configurations of other products already on that quote. This uses a “Virtual Quote.”
  • CML Code (Virtual Quote – at the end of the CML file):


    @(virtual = true)
    type Quote {
    int heavyPayloadCount;

    @(sourceContextNode = "SalesTransaction.SalesTransactionItem")
    relation robotbundle : RobotBundle[0..10] {
    heavyPayloadCount = count(Payload_Capacity_Requirement == "Heavy");
    }

    @(sourceContextNode = "SalesTransaction.SalesTransactionItem")
    relation warranty : Warranty[0..10];

    @(sourceContextNode = "SalesTransaction.SalesTransactionItem")
    relation extWarranty : ExtWarranty[0..10];

    require(robotbundle[RobotBundle], warranty[Warranty], "Robot requires Warranty");
    require(robotbundle.heavyPayloadCount > 3, extWarranty[ExtWarranty], "Orders with >3 Heavy Payload Robots require an additional warranty check.");
    }
  • Testing:
    1. Add your main “RobotBundle” to a quote. Save the quote. The “Warranty” product should be automatically added.
    2. Configure one “RobotBundle” instance to have “Payload_Capacity_Requirement” as “Heavy.” Save. The “ExtWarranty” should NOT be added yet.
    3. Change the quantity of this “Heavy” configured “RobotBundle” on the quote to 4 (or more). Save the quote. The “ExtWarranty” product should now be automatically added because the robotbundle.heavyPayloadCount > 3 condition is met.

Key Takeaways

The Salesforce Advanced Configurator provides an incredibly robust platform for defining even the most intricate product configuration rules. By leveraging its Constraint Model Language (CML) and the various rule types, you can:

  • Ensure Valid Configurations: Prevent users from creating impossible or incorrect product combinations.
  • Guide Users: Automatically select options or suggest preferences to streamline the configuration process.
  • Automate Actions: Add related products or display critical messages dynamically.
  • Enhance User Experience: Hide or disable irrelevant options for a cleaner interface.
  • Scale Complex Logic: Manage rules for large and multifaceted product offerings.

Go Forth and Configure!

We’ve covered a lot of ground, from setting up your basic model to implementing a diverse set of rules using the provided CML. The best way to master the Advanced Configurator is to start experimenting with your own products.

Remember to check out the video this tutorial is based on for visual demonstrations of each step! You can use the CML snippets provided here as a solid foundation for your own configurations.

Happy configuring, and stay tuned to The Cloud Update for more Salesforce insights!

Leave a Comment