Compart Launches DocBridge® Communication Suite
Market launch of the DocBridge® Communication Suite: New standards in flexibility and technology in customer communication management.
MoreThis tutorial walks you through embedding DocBridge® Communication Suite’s Guided Interactive (GID) functionality into Salesforce via Visualforce and Apex.
Note: The tutorial applies to DBCS Spring 2025 (Version 1.3) and later.
1. User Action
2. Visualforce Page
3. DocBridge® Communication Suite Backend
/*
BLUEPRINT provided without maintenance, support or warranty
(C) Compart GmbH
Controller for Visualforce page that supplies URLs, OAuth token,
and upstream data for Guided Interactive.
*/
public with sharing class CpGidContact {
// Record Id of the current SObject (Contact, Opportunity, etc.)
public Id id { get; set; }
// Configuration values from custom setting DocBridgeGuidedInteractive__c
private String dbcsBaseUrl;
private String gearBaseUrl;
private String keyCloakTokenUrl;
private String documentViewerBaseUrl;
private String giIntegrationBaseUrl;
private String clientId;
private String clientSecret;
private String scope;
private String sourceObjectType;
/**
* Constructor: initialize URLs/credentials and capture record Id/type.
*/
public CpGidContact() {
// Load all endpoints & credentials from custom setting
DocBridgeGuidedInteractive__c cfg = DocBridgeGuidedInteractive__c.getInstance();
dbcsBaseUrl = cfg.DocBridgeCommunicationSuiteBaseUrl__c;
gearBaseUrl = cfg.DocBridgeGearBaseUrl__c;
keyCloakTokenUrl = cfg.KeyCloakTokenUrl__c;
documentViewerBaseUrl = cfg.DocumentViewerBaseUrl__c;
giIntegrationBaseUrl = cfg.GuidedInteractiveIntegrationBaseUrl__c;
clientId = cfg.GuidedInteractiveAuthClientId__c;
clientSecret = cfg.GuidedInteractiveAuthClientSecret__c;
scope = cfg.GuidedInteractiveAuthClientScope__c;
// Capture record Id from URL and determine its type
id = ApexPages.CurrentPage().getParameters().get('Id');
sourceObjectType = id.getSObjectType().getDescribe().getName();
}
/** @return Base URL for DocBridge Communication Suite assets */
public String getDbcsBaseBaseUrl() {
return dbcsBaseUrl;
}
/** @return Base URL for Guided Interactive integration assets */
public String getGiIntegrationBaseUrl() {
return giIntegrationBaseUrl;
}
/**
* @return OAuth access token via client_credentials flow
* against Keycloak (or your IdP).
*/
public String getToken() {
return requestToken(clientId, clientSecret, scope, keyCloakTokenUrl);
}
/**
* @return JSON payload for upstreamData: executes
* a SOQL template fetched from CpGidTools.
*/
public String getContactInitiateGid() {
CpGidTools tools = new CpGidTools();
String baseSoql = tools.getQueryStringForObjectType(sourceObjectType);
String fullSoql = baseSoql + '\'' + id + '\'';
return tools.getPayload(fullSoql);
}
/**
* Helper: performs a POST to tokenUrl with client_id,
* client_secret, scope, grant_type=client_credentials,
* then parses JSON response for access_token.
*/
private static String requestToken(
String clientId,
String clientSecret,
String scope,
String tokenUrl
) {
// Build URL-encoded form body
String body = 'client_id=' + EncodingUtil.urlEncode(clientId, 'UTF-8')
+ '&client_secret=' + EncodingUtil.urlEncode(clientSecret, 'UTF-8')
+ '&scope=' + EncodingUtil.urlEncode(scope, 'UTF-8')
+ '&grant_type=client_credentials';
HttpRequest req = new HttpRequest();
req.setEndpoint(tokenUrl);
req.setMethod('POST');
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setHeader('Content-Length', String.valueOf(body.length()));
req.setBody(body);
HttpResponse res = new Http().send(req);
if (res.getStatusCode() == 200) {
// Deserialize into generic map and extract access_token
Map<String,Object> parsed = (Map<String,Object>) JSON.deserializeUntyped(res.getBody());
return (String) parsed.get('access_token');
}
// On failure, log and return empty
System.debug('Token request failed: ' + res.getStatus());
return '';
}
}
/*
BLUEPRINT provided without maintenance, support or warranty
(C) Compart GmbH
Utility methods to fetch SOQL templates and serialize data.
*/
public with sharing class CpGidTools {
/** Default constructor (no init needed). */
public CpGidTools() {}
/**
* Fetch the SOQL query template for the given objectType
* from custom object CpGuidedInteractiveQueries__c.
*
* @param objectType SObject API name (e.g. 'Contact')
* @return Query_String__c, e.g. "SELECT Id, Name FROM Contact WHERE Id = "
*/
public String getQueryStringForObjectType(String objectType) {
String soql = 'SELECT Query_String__c '
+ 'FROM CpGuidedInteractiveQueries__c '
+ 'WHERE ObjectType__c = \'' + objectType + '\'';
CpGuidedInteractiveQueries__c record =
(CpGuidedInteractiveQueries__c) Database.query(soql);
return record.Query_String__c;
}
/**
* Execute a full SOQL and serialize the results to JSON.
* Used for upstreamData in the Guided Interactive dialog.
*
* @param queryString Complete SOQL including WHERE clause
* @return JSON string of the resulting sObject list
*/
public String getPayload(String queryString) {
List<sObject> records = Database.query(queryString);
return JSON.serialize(records);
}
}
<apex:page controller="CpGidContact"
html-lang="en-US"
showHeader="false"
standardStylesheets="false">
<!-- 1) Core DBCS scripts -->
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-base-utils/dist/index.js"></script>
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-base-logging/dist/index.js"></script>
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-web-utils/dist/index.js"></script>
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-web-wui/dist/index.js"></script>
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-web-cockpit/dist/index.js"></script>
<!-- 2) DBCS plugins -->
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/plugins/@compart/docbridge-central-2-plugin-resource-director/dist/index.bundle.js"></script>
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/plugins/@compart/docbridge-central-2-plugin-document-viewer/dist/webpack/index.bundle.js"></script>
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/plugins/@compart/docbridge-central-2-plugin-impress/dist/webpack/index.bundle.js"></script>
<!-- 3) DBCS CSS -->
<link rel="stylesheet" href="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-web-cockpit/dist/bundle.css" />
<link rel="stylesheet" href="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-web-cockpit/dist/compart.css" />
<link rel="stylesheet" href="{!getDbcsBaseBaseUrl}/dbcs/ui/core/@compart/cp-web-wui-themes/dist/theme-base.css" />
<!-- 4) Guided Interactive integration -->
<script src="{!getDbcsBaseBaseUrl}/dbcs/ui/plugins/@compart/docbridge-central-2-plugin-guided-interactive/dist/integration/index.js"></script>
<!-- 5) Container for GID UI -->
<div id="gid" style="height: 98.5vh; border: 1px solid lightgray;"></div>
<script>
window.onload = async () => {
// Load locale files (fallback to 'en' if unsupported)
await cpWebCockpit.LocaleHandler.initLocaleFiles('{!getGiIntegrationBaseUrl}/');
await cpWebCockpit.LocaleHandler.loadLocale('en-US', '{!getGiIntegrationBaseUrl}/');
// Initialize the Guided Interactive dialog
initDialog();
};
async function initDialog() {
// 1) Fetch OAuth token
const token = '{!getToken}';
// 2) Fetch upstream JSON payload (if any)
const payload = '{!contactInitiateGid}';
let upstreamData = undefined;
if (payload) {
upstreamData = { content: payload, type: 'application/json' };
}
// 3) Create the GID dialog
GuidedInteractive.createGuidedInteractive(
document.getElementById('gid'),
{
token,
config: {
dbcsBaseUrl: '{!getDbcsBaseBaseUrl}/dbcs',
// Adjust to your DFF template locator
dffTemplate: 'resdir://static/example/components/master.dff',
upstreamData,
submitConfig: {
library: 'processing',
worklet: 'submit'
}
}
}
);
}
</script>
</apex:page>
1. Custom Settings
2. CpGidContact Controller
3. CpGidTools Utility
4. Visualforce Page