Skip to content
Integration Procedures

How to Call Integration Procedure and Data Mapper from Apex Class?

December 11, 2025

One of the most powerful aspects of OmniStudio in Salesforce is the ability to use Integration Procedures and Data Mappers from within Apex code. This gives developers the flexibility to leverage these declarative tools while maintaining the control and logic that only Apex can provide. Whether you’re building complex automations, batch jobs, or custom business logic, calling Integration Procedures and Data Mappers from Apex opens up countless possibilities.

In this guide, we’ll walk through exactly how to call both Integration Procedures and Data Mappers from your Apex classes, with real code examples, best practices, and troubleshooting tips. By the end, you’ll have a solid foundation for integrating these OmniStudio components into your Apex workflows.

Table of Contents

Why Call Integration Procedures and Data Mappers from Apex?

Before diving into the how, let’s understand the why. There are several compelling reasons to invoke these OmniStudio components from Apex:

Reusability – You build an Integration Procedure once and call it from multiple places: OmniScripts, REST APIs, Flows, and Apex classes. This eliminates code duplication and makes maintenance easier.

Declarative Power – Integration Procedures and Data Mappers are built using a visual interface with drag-and-drop components. This means non-developers can contribute to business logic, and changes can be made without recompiling code.

Complex Data Transformations – Data Mappers excel at extracting and transforming Salesforce data into structured JSON. Instead of writing SOQL queries and data transformation logic in Apex, you can leverage Data Mapper’s built-in functions and formulas.

Separation of Concerns – Your Apex code focuses on orchestration and business logic, while Integration Procedures handle data retrieval and integration with external systems. This makes code cleaner and easier to test.

Error Handling – Integration Procedures include built-in error handling with Try-Catch blocks, which can be more readable and maintainable than nested Apex try-catch structures.

Understanding the Namespace: omnistudio vs vlocity_cmt

Before you start calling anything from Apex, you need to understand which namespace to use. This depends on which version of OmniStudio your Salesforce org has installed.

For OmniStudio (Standard Runtime) – Use the omnistudio namespace. This is the newer, cloud-native version of OmniStudio that uses Salesforce standard objects. If your org is on a recent Salesforce release with OmniStudio, this is what you’ll use.

For Salesforce Industries (Managed Package Runtime) – Use the vlocity_cmt namespace. This is the original managed package version that predates OmniStudio and is still widely used in industry implementations like Communications, Health, and Insurance.

To check which version your org has, go to Setup > Installed Packages and look for either “OmniStudio” or “Vlocity Industries” (or similar). The active package determines which namespace you’ll use in your Apex code.

In the examples below, we’ll show both approaches. If you’re using OmniStudio standard runtime, use omnistudio. If you’re on Salesforce Industries (Vlocity), use vlocity_cmt.

Part 1: Calling an Integration Procedure from Apex

Step 1: Understand Your Integration Procedure’s Type and SubType

Before you can call an Integration Procedure from Apex, you need to know two pieces of information:

  1. Type – The first part of the Integration Procedure identifier
  2. SubType – The second part of the Integration Procedure identifier

In OmniStudio, Integration Procedures are identified by the format Type_SubType. For example, if you have an Integration Procedure named “get_contactdata”, the Type might be “get” and the SubType might be “contactdata”. When called from Apex, you’ll reference it as “get_contactdata” using the naming convention.

To find your Integration Procedure’s Type and SubType, navigate to OmniStudio > Integration Procedures and open your procedure. You’ll see the Type and SubType fields displayed in the procedure configuration.

Step 2: Create Maps for Input, Output, and Options

The runIntegrationService method requires three maps:

Map<String, Object> ipInput = new Map<String, Object>();
Map<String, Object> ipOutput = new Map<String, Object>();
Map<String, Object> ipOptions = new Map<String, Object>();

ipInput Map – Contains the data your Integration Procedure expects as input. For example, if your Integration Procedure needs a Contact ID to fetch contact details, you’ll put that here.

ipOutput Map – This is where the result of the Integration Procedure execution will be stored. It’s passed by reference, so the method will populate it with the response.

ipOptions Map – Contains configuration options for how the Integration Procedure should behave. Common options include:

  • isDebug – Set to true if you want detailed debug information
  • chainable – Set to true if the Integration Procedure is configured for chaining (handling long-running procedures)
  • queueableChainable – Set to true for asynchronous execution

Even if you don’t need any options, the options map must be passed (it can be empty).

Step 3: Populate the Input Map

Add the data your Integration Procedure needs to the input map. The structure depends entirely on what your procedure expects.

String recordId = '0011y00000abcde';
ipInput.put('recordId', recordId);

If your Integration Procedure expects nested data, you can create nested maps:

Map<String, Object> contactData = new Map<String, Object>();
contactData.put('firstName', 'John');
contactData.put('lastName', 'Doe');
ipInput.put('contact', contactData);

Step 4: Call the Integration Procedure

Now comes the actual call. The syntax is:

ipOutput = (Map<String, Object>) omnistudio.IntegrationProcedureService.runIntegrationService(
    'Type_SubType',
    ipInput,
    ipOptions
);

Or for Salesforce Industries (Vlocity):

ipOutput = (Map<String, Object>) vlocity_cmt.IntegrationProcedureService.runIntegrationService(
    'Type_SubType',
    ipInput,
    ipOptions
);

Breaking this down:

  • Replace ‘Type_SubType’ with your actual Integration Procedure identifier (e.g., ‘get_contactdata’)
  • The method returns an Object, so we cast it to Map<String, Object>
  • Pass your input map and options map as parameters

Step 5: Handle the Response

After the call completes, your response will be in the ipOutput map. You can now work with it:

// Log the entire response
System.debug('IP Output: ' + JSON.serialize(ipOutput));

// Extract specific values
String contactName = (String) ipOutput.get('contactName');
Boolean isSuccess = (Boolean) ipOutput.get('success');

// Handle nested data
Map<String, Object> contactDetails = (Map<String, Object>) ipOutput.get('contactData');

Complete Example: Calling an Integration Procedure

Here’s a complete, realistic example:

public class ContactDataFetcher {
    public static void fetchContactDetails(String recordId) {
        try {
            // Step 1: Create maps
            Map<String, Object> ipInput = new Map<String, Object>();
            Map<String, Object> ipOutput = new Map<String, Object>();
            Map<String, Object> ipOptions = new Map<String, Object>();
            
            // Step 2: Populate input
            ipInput.put('recordId', recordId);
            
            // Step 3: Call the Integration Procedure
            ipOutput = (Map<String, Object>) omnistudio.IntegrationProcedureService.runIntegrationService(
                'get_contactdata',
                ipInput,
                ipOptions
            );
            
            // Step 4: Handle response
            System.debug('Response from Integration Procedure: ' + JSON.serialize(ipOutput));
            
            // Extract data from response
            String contactName = (String) ipOutput.get('name');
            String email = (String) ipOutput.get('email');
            
            // Use the extracted data
            System.debug('Contact Name: ' + contactName);
            System.debug('Email: ' + email);
            
        } catch (Exception e) {
            System.debug('Error calling Integration Procedure: ' + e.getMessage());
            System.debug('Stack trace: ' + e.getStackTraceString());
        }
    }
}

Part 2: Calling a Data Mapper from Apex

Data Mappers work slightly differently from Integration Procedures. Instead of using runIntegrationService, you’ll use the DRGlobal class from the Vlocity or OmniStudio package.

Understanding Data Mapper Types

Before calling a Data Mapper, know that Data Mappers come in three flavors:

  1. Extract – Reads data from Salesforce objects and returns results in JSON format
  2. Load – Writes data back to Salesforce objects from JSON input
  3. Transform – Performs intermediate data transformations without hitting the database

From Apex, you can call all three types using the same method.

Step 1: Determine Your Data Mapper Name

Find your Data Mapper’s exact name by navigating to OmniStudio > Data Mapper and opening it. The name you use in your Apex code is exactly what appears in the Data Mapper list (e.g., ‘ExtractContactInfo’, ‘GetUserDetails’).

Step 2: Create Your Input Data

Data Mappers accept input as either a Map<String, Object> or as a JSON string. We’ll use maps for this example, as they’re type-safe:

Map<String, Object> dmInput = new Map<String, Object>();
dmInput.put('userId', 'userId12345');
dmInput.put('includeOrders', true);

Step 3: Call the Data Mapper

The method syntax is:

vlocity_ins.DRProcessResult result = vlocity_ins.DRGlobal.process(dmInput, 'DataMapperName');

Or using the newer standard runtime:

omnistudio.DRProcessResult result = omnistudio.DRGlobal.process(dmInput, 'DataMapperName');

The method returns a DRProcessResult object, which we then need to convert to a usable format.

Step 4: Process the Result

The tricky part with Data Mappers is that the result comes back as a DRProcessResult object, which needs to be deserialized. Here are the common ways to handle it:

For Extract Data Mappers (returning a list of records):

List<Map<String, Object>> extractResult = (List<Map<String, Object>>) result.toJsonList();

For Transform or Extract (returning a single map):

Map<String, Object> transformResult = result.convertToMap();

To serialize and debug:

System.debug('Data Mapper result: ' + JSON.serialize(result.convertToMap()));

Complete Example: Calling a Data Mapper

Here’s a full example of calling an Extract Data Mapper:

public class UserDataExtractor {
    public static void extractUserInfo(String userId) {
        try {
            // Step 1: Create input map
            Map<String, Object> dmInput = new Map<String, Object>();
            dmInput.put('userId', userId);
            
            // Step 2: Call the Data Mapper
            vlocity_ins.DRProcessResult result = vlocity_ins.DRGlobal.process(dmInput, 'GetUserForContact');
            
            // Step 3: Convert result to map
            List<Map<String, Object>> userList = (List<Map<String, Object>>) result.toJsonList();
            
            // Step 4: Process results
            if (userList != null && userList.size() > 0) {
                Map<String, Object> userMap = userList.get(0);
                String userName = (String) userMap.get('Name');
                String userEmail = (String) userMap.get('Email');
                
                System.debug('User Name: ' + userName);
                System.debug('User Email: ' + userEmail);
            } else {
                System.debug('No user data found');
            }
            
        } catch (Exception e) {
            System.debug('Error calling Data Mapper: ' + e.getMessage());
        }
    }
}

JSON String Input Alternative

If you prefer passing input as a JSON string instead of a map, you can do this:

String dataJson = '{"userId":"userId12345","includeOrders":true}';
vlocity_ins.DRProcessResult result = vlocity_ins.DRGlobal.processObjectsJSON(dataJson, 'GetUserForContact');

This approach is useful when you already have JSON data from an API call or another source.

Part 3: Advanced Patterns – Integration Procedures Calling Data Mappers

A common pattern in OmniStudio development is having an Integration Procedure call a Data Mapper internally. But what if you need to do this from Apex? You would:

  1. Call the Integration Procedure from Apex (which internally calls a Data Mapper)
  2. The result returned to Apex will already include the Data Mapper’s processed data

This is cleaner than calling both separately, as the Integration Procedure handles orchestration. However, if you need more control, you can call them sequentially from Apex:

// First, call Data Mapper to extract data
Map<String, Object> dmInput = new Map<String, Object>();
dmInput.put('recordId', '0011y00000abcde');
vlocity_ins.DRProcessResult dmResult = vlocity_ins.DRGlobal.process(dmInput, 'ExtractContactData');
List<Map<String, Object>> contactData = (List<Map<String, Object>>) dmResult.toJsonList();

// Then, pass that data to an Integration Procedure
Map<String, Object> ipInput = new Map<String, Object>();
ipInput.put('contactData', contactData.get(0));
Map<String, Object> ipOutput = (Map<String, Object>) vlocity_cmt.IntegrationProcedureService.runIntegrationService(
    'process_contact',
    ipInput,
    new Map<String, Object>()
);

System.debug('Final result: ' + JSON.serialize(ipOutput));

Handling Data: Serialization and Deserialization

When working with Integration Procedures and Data Mappers from Apex, you’ll frequently need to convert between different data formats. Here’s what you need to know:

JSON Serialization

When you have a Map or object and need to convert it to JSON string:

Map<String, Object> data = new Map<String, Object>();
data.put('name', 'John Doe');
data.put('email', 'john@example.com');

String jsonString = JSON.serialize(data);
System.debug(jsonString); // {"name":"John Doe","email":"john@example.com"}

JSON Deserialization

When you have a JSON string and need to convert it to a map:

String jsonString = '{"name":"John Doe","email":"john@example.com"}';
Map<String, Object> data = (Map<String, Object>) JSON.deserializeUntyped(jsonString);

String name = (String) data.get('name');

Working with Lists

Data Mappers often return lists of records. Handle them carefully:

List<Map<String, Object>> records = (List<Map<String, Object>>) result.toJsonList();

for (Map<String, Object> record : records) {
    String id = (String) record.get('Id');
    String name = (String) record.get('Name');
    System.debug('Record: ' + id + ' - ' + name);
}

Error Handling and Debugging

Things can go wrong, and knowing how to troubleshoot is essential.

Common Errors and Solutions

Error: “Type not found: omnistudio.IntegrationProcedureService”

  • Solution: Your org doesn’t have OmniStudio installed. Check Setup > Installed Packages. Use vlocity_cmt instead if you have Salesforce Industries.

Error: “Unknown named argument: runIntegrationService”

  • Solution: You’re using the wrong namespace or syntax. Verify you’re using the correct package namespace for your org.

Error: “Null pointer exception when accessing output data”

  • Solution: The Integration Procedure or Data Mapper didn’t return expected data. Add debug logging to see what actually returned:
System.debug('Full output: ' + JSON.serialize(ipOutput));

Error: “Governor limit exceeded”

  • Solution: You’re hitting Salesforce’s governor limits. If calling from Batch Apex or in a loop, consider:
    • Bulkifying your code (processing multiple records in one call instead of many calls)
    • Using chainable Integration Procedures (check the Chainable option in your IP configuration)
    • Setting chainable: true in your options map if the IP supports it

Debugging Techniques

Enable Debug Output:

Map<String, Object> ipOptions = new Map<String, Object>();
ipOptions.put('isDebug', true);

Map<String, Object> ipOutput = (Map<String, Object>) omnistudio.IntegrationProcedureService.runIntegrationService(
    'get_contactdata',
    ipInput,
    ipOptions
);

This adds detailed debugging information to the response.

Log Everything:

System.debug('Input: ' + JSON.serialize(ipInput));
System.debug('Output: ' + JSON.serialize(ipOutput));
System.debug('Output keys: ' + ipOutput.keySet());

Use Execute Anonymous:

In the Developer Console, use Debug > Open Execute Anonymous Window to quickly test your Apex code without creating a class:

Map<String, Object> dmInput = new Map<String, Object>();
dmInput.put('userId', 'test123');
vlocity_ins.DRProcessResult result = vlocity_ins.DRGlobal.process(dmInput, 'GetUserData');
System.debug('Result: ' + JSON.serialize(result.convertToMap()));

Check Debug Logs:

Always review debug logs to understand the flow. Go to Setup > Debug Logs to enable logging for your user, then run your code and review the logs. Look for:

  • Any exceptions thrown
  • The actual values being passed and returned
  • Timing information to spot performance issues

Best Practices

When calling Integration Procedures and Data Mappers from Apex, follow these practices:

1. Always Use Try-Catch Blocks

Integration Procedures and Data Mappers can throw exceptions. Always wrap your calls in try-catch:

try {
    Map<String, Object> ipOutput = (Map<String, Object>) omnistudio.IntegrationProcedureService.runIntegrationService(
        'get_data',
        ipInput,
        ipOptions
    );
} catch (Exception e) {
    System.debug('Error: ' + e.getMessage());
    System.debug('Stack: ' + e.getStackTraceString());
    // Handle the error appropriately
}

2. Validate Input Data

Don’t assume your input map will be populated correctly. Validate:

if (String.isBlank(recordId)) {
    throw new IllegalArgumentException('Record ID is required');
}

if (ipInput == null || ipInput.isEmpty()) {
    throw new IllegalArgumentException('Input data is required');
}

3. Check Response Data Types

Maps can contain various data types. Always cast carefully:

Object rawValue = ipOutput.get('someField');
if (rawValue instanceof String) {
    String stringValue = (String) rawValue;
} else if (rawValue instanceof Integer) {
    Integer intValue = (Integer) rawValue;
} else if (rawValue instanceof List<Object>) {
    List<Object> listValue = (List<Object>) rawValue;
}

4. Limit Data Returned

If your Data Mapper can return thousands of records, paginate or filter:

// In your Data Mapper, add a Limit clause
// Or from Apex, check the size:
List<Map<String, Object>> results = (List<Map<String, Object>>) result.toJsonList();
if (results.size() > 1000) {
    System.debug('Warning: Large result set detected');
    // Handle accordingly
}

5. Use Meaningful Variable Names

Make your code readable:

// Good
Map<String, Object> contactDataInput = new Map<String, Object>();
Map<String, Object> contactDataOutput = new Map<String, Object>();

// Confusing
Map<String, Object> m1 = new Map<String, Object>();
Map<String, Object> m2 = new Map<String, Object>();

6. Document the Expected Input/Output

Add comments explaining what the Integration Procedure or Data Mapper expects and returns:

/**
 * Fetches contact data from an Integration Procedure
 * Expected Input: recordId (String) - The ID of the contact record
 * Expected Output: 
 *   - contactName (String)
 *   - contactEmail (String)
 *   - contactPhone (String)
 */
public static Map<String, Object> getContactData(String recordId) {
    // Implementation
}

Performance Considerations

When calling Integration Procedures and Data Mappers from Apex at scale, consider:

Governor Limits

Each Integration Procedure or Data Mapper call consumes resources:

  • SOQL queries (100 per sync transaction)
  • DML operations (150 per sync transaction)
  • CPU time (10 seconds per sync transaction)
  • Heap size (6 MB per sync transaction)

Monitor your Limits:

System.debug('SOQL Queries: ' + Limits.getQueries() + '/' + Limits.getLimitQueries());
System.debug('DML Rows: ' + Limits.getDmlRows() + '/' + Limits.getLimitDmlRows());

System.debug(‘SOQL Queries: ‘ + Limits.getQueries() + ‘/’ + Limits.getLimitQueries());

System.debug(‘DML Rows: ‘ + Limits.getDmlRows() + ‘/’ + Limits.getLimitDmlRows());

Asynchronous Processing

For large-scale operations, consider using Batch Apex or Queueable Apex to process data asynchronously and reset governor limits between batches:

global class DataProcessorBatch implements Database.Batchable<SObject> {
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id FROM Contact WHERE CreatedDate = TODAY');
    }
    
    global void execute(Database.BatchableContext bc, List<Contact> contacts) {
        for (Contact c : contacts) {
            // Call Integration Procedure or Data Mapper here
            // Governor limits reset for each batch
        }
    }
    
    global void finish(Database.BatchableContext bc) {
        // Handle completion
    }
}

Caching Results

If calling the same Integration Procedure or Data Mapper repeatedly with the same inputs, cache the results:

private static Map<String, Map<String, Object>> resultCache = new Map<String, Map<String, Object>>();

public static Map<String, Object> getContactDataCached(String recordId) {
    if (resultCache.containsKey(recordId)) {
        return resultCache.get(recordId);
    }
    
    Map<String, Object> result = getContactData(recordId);
    resultCache.put(recordId, result);
    return result;
}

Testing Integration Procedures and Data Mappers

Writing test classes for Apex code that calls Integration Procedures can be challenging because these components may make external calls. Here’s a testing approach:

Unit Test with Mocking

@isTest
private class ContactDataFetcherTest {
    @isTest
    static void testFetchContactDetails() {
        // Arrange
        String recordId = '0011y00000abcde';
        
        // Act
        Test.startTest();
        ContactDataFetcher.fetchContactDetails(recordId);
        Test.stopTest();
        
        // Assert
        // Check that expected behavior occurred
        // (Note: Testing Integration Procedures in unit tests is limited without mocking)
    }
}

For more advanced testing, consider mocking external callouts or creating integration test environments.

Real-World Scenarios

Scenario 1: Processing Orders from an External System

You receive orders from an external system and need to create Order records in Salesforce with related Order Items.

public class OrderProcessor {
    public static void processExternalOrder(String externalOrderJson) {
        try {
            // Parse the JSON
            Map<String, Object> externalOrder = (Map<String, Object>) JSON.deserializeUntyped(externalOrderJson);
            
            // Call Integration Procedure to validate and transform data
            Map<String, Object> ipInput = new Map<String, Object>();
            ipInput.put('externalOrder', externalOrder);
            
            Map<String, Object> ipOutput = (Map<String, Object>) vlocity_cmt.IntegrationProcedureService.runIntegrationService(
                'order_process',
                ipInput,
                new Map<String, Object>()
            );
            
            // Check if processing was successful
            Boolean isSuccess = (Boolean) ipOutput.get('success');
            if (isSuccess) {
                String salesforceOrderId = (String) ipOutput.get('orderId');
                System.debug('Order created successfully: ' + salesforceOrderId);
            } else {
                String errorMessage = (String) ipOutput.get('errorMessage');
                System.debug('Order processing failed: ' + errorMessage);
            }
            
        } catch (Exception e) {
            System.debug('Unexpected error: ' + e.getMessage());
        }
    }
}

Scenario 2: Extracting Data for Reporting

You need to extract complex related data for a custom report:

public class ReportDataExtractor {
    public static List<Map<String, Object>> getAccountWithContacts(String accountId) {
        try {
            // Use Data Mapper to extract account and related contacts
            Map<String, Object> dmInput = new Map<String, Object>();
            dmInput.put('accountId', accountId);
            
            vlocity_ins.DRProcessResult result = vlocity_ins.DRGlobal.process(dmInput, 'ExtractAccountWithContacts');
            List<Map<String, Object>> accountData = (List<Map<String, Object>>) result.toJsonList();
            
            System.debug('Extracted ' + accountData.size() + ' records');
            return accountData;
            
        } catch (Exception e) {
            System.debug('Error extracting data: ' + e.getMessage());
            return new List<Map<String, Object>>();
        }
    }
}

Conclusion

Calling Integration Procedures and Data Mappers from Apex gives you the best of both worlds: the declarative power and flexibility of OmniStudio components combined with the control and logic of Apex. By following the patterns and best practices outlined in this guide, you can build robust, maintainable, and scalable solutions.

Key takeaways:

  • Use IntegrationProcedureService.runIntegrationService() for calling Integration Procedures
  • Use DRGlobal.process() for calling Data Mappers
  • Always validate input, handle exceptions, and debug thoroughly
  • Consider performance implications, especially at scale
  • Test your code in sandboxes before deploying to production

With this knowledge, you’re ready to integrate OmniStudio components into your Apex workflows and unlock new possibilities in your Salesforce implementations.

Watch the Complete Tutorial

Want to see this in action? Check out our step-by-step video tutorial that walks through calling Integration Procedures and Data Mappers from Apex with live coding demonstrations and real-world examples.

Watch on YouTube: 

In this video, you’ll see:

  • How to identify Integration Procedure Type and SubType
  • Complete code examples for calling both Integration Procedures and Data Mappers
  • Real-time response handling and debugging
  • Common mistakes and how to avoid them
  • Performance optimization techniques

Ready to Master OmniStudio Apex Integration?

If this guide helped you understand how to leverage Integration Procedures and Data Mappers in your Apex code, you’re on the right track. But OmniStudio mastery goes beyond just calling components – it requires understanding the entire ecosystem.

What’s Next?

Explore more Salesforce tutorials on our blog:

Connect With 2Creative Solutions

Have questions about OmniStudio, Apex development, or Salesforce implementation? We’re here to help.

📞 Book a Free Consultation: https://2creative.ca/

Our Salesforce experts can help you:

  • Design custom OmniStudio solutions
  • Optimize Apex code for performance
  • Implement complex Salesforce Industries projects
  • Train your team on best practices

Subscribe to Our YouTube Channel:

https://www.youtube.com/@2CreativeSolutions

Get regular Salesforce tutorials, tips, and deep dives into OmniStudio, Apex development, and Salesforce best practices.

🤝 Connect on Social Media:

Keep Reading

Related Articles and Resources

Best Practice To Follow For Omnistudio Data Mapper
June 11, 2025

Best Practice To Follow For Omnistudio Data Mapper

When building efficient and scalable solutions in...

Ultimate Salesforce Agentforce Guide: Your Complete Expert Resource
October 11, 2025

Ultimate Salesforce Agentforce Guide: Your Complete Expert Resource

Salesforce Agentforce marks the next big leap in AI,...

Revenue Cloud Advanced for Subscription Businesses: Real Use Cases
January 7, 2026

Revenue Cloud Advanced for Subscription Businesses: Real Use Cases

Picture this: It’s month-end, and your finance team...

What is Salesforce Revenue Cloud Advanced? A Simple Guide
September 30, 2025

What is Salesforce Revenue Cloud Advanced? A Simple Guide

Why Salesforce Revenue Cloud Advanced? Here’s...

Transaction Management in Salesforce: The Complete Expert’s Guide to Data Integrity, Consistency, and Advanced Implementation
December 29, 2025

Transaction Management in Salesforce: The Complete Expert’s Guide to Data Integrity, Consistency, and Advanced Implementation

If you’re working with Salesforce – whether&...

Using Datatable in Omniscript and pass data from OS to flexcard
November 9, 2024

Using Datatable in Omniscript and pass data from OS to flexcard

This blog will cover how data pass from Omniscript to...