Using Token Replacements
Using Token Replacements
Replacement tokens insert Salesforce user, org, or record values into supported CloudTools text settings. Enter a token in braces, such as {UserEmail} or {Record.Name}, and CloudTools resolves it when the component uses that setting. One shared configuration can therefore adapt to the person viewing the page and the record they are viewing.
Use tokens only in fields documented as supporting token replacement. Component configuration, prompts, and message fields differ in what they resolve; not every text input or connector action performs replacement automatically. See the individual component or action guide for supported fields. These text placeholders are separate from the OAuth access and refresh tokens used to authorize connectors.
Token syntax
- Keep the braces:
{UserEmail}. You can combine literal text and multiple tokens, for examplePrepared for {UserName}: {Record.Name}. - Use a dot to select a record field:
{Record.Email}. Use the Salesforce field API name, including any custom-field or namespace suffix. - Add one optional transformation after a vertical bar:
{UserEmail|lower}. - Token lookup is case-insensitive. Use the spelling shown below and exact field API names so record fields can be selected reliably.
Values come from the current Salesforce execution context. In an interactive component, user tokens describe the Salesforce viewer, not the external account signed in through a delegated connector. A token supplies a value; it does not change the connector identity or grant external access.
User tokens
The following table lists all built-in user tokens and their aliases. Each alias resolves to the same value as its main token.
| Token | Aliases | Value |
|---|---|---|
{UserId} | None | The current Salesforce user’s Salesforce ID. |
{UserEmail} | {Email} | The user’s email address. |
{UserName} | None | The user’s full name. |
{UserFirstName} | {FirstName} | The user’s first name. |
{UserLastName} | {LastName} | The user’s last name. |
{UserUsername} | {Username} | The Salesforce login username, which can differ from the user’s email address. |
{ProfileId} | None | The user’s Salesforce profile ID. |
{Locale} | None | The user’s Salesforce locale code. |
{Language} | None | The user’s Salesforce language code. |
{TimeZone} | None | The user’s Salesforce time zone ID, such as America/Chicago. |
Organization tokens
| Token | Aliases | Value |
|---|---|---|
{OrgId} | {OrganizationId} | The Salesforce organization ID. |
{OrgUrl} | None | The Salesforce org’s domain URL, such as https://example.my.salesforce.com. |
Record tokens
| Token or pattern | Value | Requirements |
|---|---|---|
{RecordId} | The current Salesforce record ID. | The caller must supply or derive a record ID. This token alone does not confirm access to the record. |
{ObjectApiName} | The current Salesforce object API name, such as Account or Contact. | An object context must be available. |
{RecordObjectApiName} | The object API name resolved from the record context. | Record context must be loaded. In Apex, include a {Record} or {Record.FieldApiName} token, or request record fields explicitly, to trigger that load. |
{Record.FieldApiName} | The value of a direct field on the current record. Examples: {Record.Name}, {Record.Email}, and {Record.External_User_Id__c}. | A current, readable record and a readable field with that API name. Replace FieldApiName with an actual field. |
{Record} | The loaded record-field map serialized as JSON. | Readable record context. This contains the selected fields, not every field on the record. |
The {Record.FieldApiName} pattern supports direct standard and custom fields on the current object; the possible field names depend on that object’s schema. There is no fixed list of record-field tokens. A lookup field such as {Record.AccountId} returns the related record’s ID. The built-in record loader does not query relationship paths such as {Record.Account.Name}, related lists, or child records.
{Record} uses fields explicitly requested by the calling component or code, together with fields referenced by other record tokens in the values being resolved. If no readable requested fields are selected, the loader falls back to Id and Name where available and readable. Do not assume that {Record} includes the complete record or that its fields are identical across components.
Using record-specific tokens
- Place the component on a record page for the intended object, or use a component that explicitly supplies record context. Home and app pages normally have no current record.
- Choose a field on that object and copy its Field Name / API Name from Setup > Object Manager > Fields & Relationships. Use
Microsoft_User_ID__c, for example, rather than its display label. Include the namespace prefix for a namespaced field. - Enter the token in a supported text setting, such as
{Record.Email}for a Contact email or{Record.Microsoft_User_ID__c}for an external identifier stored in a custom field. - Confirm that the viewer can read the object, record, and field, and that the field has a value. The record loader respects sharing and object and field access.
- Save the configuration and test it on multiple records using the intended user’s access. Check that the resolved value has the format the external operation expects.
Record context must match the record’s actual object. A token valid on Contact may not work on Account, and a shared configuration should use fields available on the object where it is saved. For example, {Record.Email} targets a Contact’s email, while {UserEmail} targets the Salesforce viewer’s email. A Salesforce ID such as {RecordId} is not an external service’s user or resource ID.
For a record-specific prompt, use text such as Summarize the latest activity for {Record.Name}. Requested by {UserName}. Only the resolved values in the supported prompt are included; placing a component on a record page does not automatically send the entire record. Choose fields containing information you intend to send to the external service.
Page and custom context tokens
The JavaScript connectorTokenUtils helper exposes these additional tokens when the calling component supplies a page reference. These are LWC context tokens, not built-in Apex user or org tokens.
| Token or pattern | Value |
|---|---|
{PageType} | The page reference’s attributes.actionName, when nonblank; otherwise its type. It remains unavailable without that context. |
{PageReference} | The supplied page reference object serialized as JSON. |
{PageReference.type} | The supplied page reference’s type. |
{PageReference.attributes.Key} | A supplied page attribute, such as {PageReference.attributes.recordId}. Replace Key with an existing attribute name. |
{PageReference.state.Key} | A supplied page state value, such as {PageReference.state.c__recordId}. Replace Key with an existing state key. |
For custom development, the JavaScript resolver also accepts caller-supplied context keys and nested object paths. For example, passing extraContext: { Project: { Code: 'PRJ-42' } } to resolveTokensWithContext enables {Project.Code}. These are application-defined values rather than additional guaranteed built-in tokens. Plain context keys can be used in braces, and dot paths select existing nested values. Objects and arrays resolve to JSON text.
Text transformations
Use {Token|transform} to format a resolved value. These are all supported transformations. Use one per token; chaining transformations, fallback expressions, and conditional expressions are not supported.
| Transformation | Example | Behavior |
|---|---|---|
lower | {UserEmail|lower} | Converts text to lowercase. |
upper | {Record.Name|upper} | Converts text to uppercase. |
trim | {Record.External_User_Id__c|trim} | Removes leading and trailing whitespace. |
url | {Record.Name|url} | URL-encodes the value. JavaScript uses encodeURIComponent; Apex uses UTF-8 form encoding, including + for spaces. Verify the encoding expected by the destination. |
odata | displayName eq '{Record.Name|odata}' | Doubles single quotes within an OData string value. For example, O’Brien becomes O”Brien. Add the surrounding quotes in the filter yourself. |
Transformations apply after lookup and do not fetch additional data. An unrecognized transformation leaves the resolved value unchanged. The odata transformation escapes string-literal quotes; it does not URL-encode the filter or validate the complete query.
Resolving tokens in custom code
In an LWC, use resolveTokensWithContext from c/connectorTokenUtils to gather context and resolve supported values before passing them to a connector library. The helper can process a string, an array, or an object containing strings, and automatically requests direct fields referenced by record tokens. The following example uses the repository’s same-namespace module imports inside a component method:
const prompt = await resolveTokensWithContext(
'Summarize the latest activity for {Record.Name}. Requested by {UserName}.',
{
component: this,
recordId: this.recordId,
objectApiName: this.objectApiName,
strict: true
}
);
// Pass prompt to the connector operation's message or prompt input.
Import the helper with import { resolveTokensWithContext } from 'c/connectorTokenUtils';. Custom Apex in this repository can use CloudToolsTokenResolver.resolveTokenString(value, recordId, objectApiName); the Apex record-loading path requires both record ID and object API name. These examples describe internal development helpers. Calling a connector action directly does not automatically perform token replacement.
Developer API reference
Choose between gathering Salesforce context and resolving values against context you already have. The JavaScript functions below are named exports from c/connectorTokenUtils.
| Function | Behavior |
|---|---|
resolveTokensWithContext(value, options) | Asynchronously gathers context, merges explicit record fields with fields detected in tokens, and resolves strings recursively in the supplied value. |
getTokenContext(options) | Asynchronously gathers context without performing replacement. Request needed fields through recordFieldApiNames when using this separately. |
getTokenContextFromComponent(component, pageReference, options) | Convenience wrapper for gathering context from a component and page reference. |
resolveTokenString(value, context, options) | Synchronously resolves a single string using supplied context. Performs no Salesforce queries; non-string values pass through unchanged. |
resolveTokens(value, context, options) | Synchronously resolves strings in arrays and plain objects using supplied context. Object property names are unchanged; numbers, booleans, null, and undefined pass through unchanged. |
Context and resolution options
| Option | Use |
|---|---|
component, pageReference | Supply the component and current page reference to derive record and page context. The helper does not wire the page reference itself. |
recordId, objectApiName | Explicit record context takes precedence over component or page-derived values. The JavaScript record loader can infer the object from the record ID when objectApiName is absent. |
recordFieldApiNames | An array of direct field API names to load, for example ['Name', 'Industry']. resolveTokensWithContext also detects fields referenced in tokens. Use this option to control fields included in {Record}. |
includeServerContext | Defaults to true. Set false to skip loading user and org context from Apex; the imported Salesforce user ID remains available. |
includeRecordContext | Defaults to true. Set false to skip loading record fields; supplied or derived record IDs can still be available. |
extraContext | Additional context for application-defined tokens. Merged last, so it can override existing context keys. Use deliberate key names to avoid replacing user, org, or record values accidentally. |
strict | Defaults to false. Set true on a resolution function to throw for unknown or null-valued tokens. It does not reject empty strings or unrecognized transformations. |
JavaScript context-loading failures are caught by the helper so resolution can continue with the context available. Use strict resolution and catch its error when missing values should prevent an external request. Otherwise, unresolved token text can reach the connector. Validate the resolved identifier or prompt before invoking the external operation.
Reuse context for several values
Gather context once when resolving several related values against the same record and user. Request every required field up front; synchronous resolution does not load fields discovered later. Gather fresh context when the user or record changes.
import { getTokenContext, resolveTokens } from 'c/connectorTokenUtils';
// Inside an async component method:
const context = await getTokenContext({
component: this,
recordFieldApiNames: ['Name', 'Industry']
});
const values = resolveTokens(
{
title: 'Account: {Record.Name}',
prompt: 'Summarize {Record.Name} in the {Record.Industry} industry.'
},
context,
{ strict: true }
);
// Use values.title and values.prompt after successful resolution.
Apex overloads and strict resolution
CloudToolsTokenResolver provides these static overloads for code in the package’s namespace. The class is public rather than global, so these are internal development APIs, not subscriber-org Apex APIs.
resolveTokenString(value)resolves current user and org tokens.resolveTokenString(value, recordId, objectApiName)adds record context and detects direct field tokens.resolveTokenString(value, recordId, objectApiName, recordFieldApiNames)also requests explicit record fields.resolveTokenString(value, context, recordId, objectApiName, recordFieldApiNames, strict)accepts aCloudToolsContext.ContextObjectand controls strict resolution. The shorter overloads use strict=false.
// Inside package-namespace Apex with a current Account record ID:
String prompt = CloudToolsTokenResolver.resolveTokenString(
'Summarize {Record.Name} for {UserName}.',
CloudToolsContext.getContext(),
accountRecordId,
'Account',
new List<String>{ 'Name' },
true
);
// Invoke the connector only after successful resolution.
Apex resolves one string per call and throws CloudToolsException for an unresolved token in strict mode. Record loading can also raise query or access errors; handle these in the calling application. Unlike the JavaScript helper, the Apex resolver does not suppress record-loading exceptions.
Parsing and output behavior
- Replacement is a single pass over the original input. A replacement value containing another token is not resolved again automatically.
- Plain token keys and path lookup normalize case and remove non-alphanumeric characters. Avoid custom keys that differ only by punctuation or case. Record field selection still requires valid field API names.
- Numbers and booleans become text when used as replacement values; objects and arrays become JSON. No date, currency, or locale formatting transformation is provided.
- Strict mode validates token availability, not the final query, URL, HTML, or external identifier. Apply the encoding and validation required by the destination. Token replacement does not automatically HTML-escape or JSON-escape scalar values embedded in a larger string.
- Both implementations support the same five transformation names, but URL encoding differs as described above. Test the destination’s expected encoding when moving resolution between JavaScript and Apex.
Troubleshooting unresolved tokens
| Symptom | What to check |
|---|---|
| The token appears literally in the result | Confirm that the field supports replacement, the token exists, and its context value is available. Unknown or null values remain as the original token by default. |
| Record tokens do not resolve | Check record context, object matching, the direct field API name, record access, field permissions, and whether the field is populated. On a page without record context, use a fixed value or suitable user token. |
| A token becomes blank | An available empty string replaces the token with blank text. Null values instead remain unresolved by default. Supply a populated field or change the configuration. |
| Unknown token error | The calling code enabled strict resolution. Strict mode throws for unknown or null-valued tokens rather than preserving them; correct the token or supply its context. |
| The external service rejects a resolved value | Check the expected identifier and format. Salesforce IDs and usernames do not necessarily match external IDs and usernames. Also check the connector’s authorization and resource access. |
| Formatting did not change | Use one of the five supported transformation names and one transformation per token. |
See Configure a CloudTools Component for saving personal and shared configurations, then refer to the individual component guide for the fields that support replacement.