Friday, April 29, 2016

[Salesforce] The Sobject Crusade: AllowedEmailDomain

Back to the Sobject Crusade list.

Source: AllowedEmailDomain

To enable this object you need to contact support: I had no way to enable it quickly so I'm just gonna post what this feature means.

The AllowedEmailDomain object is used to store the allowed email domains for your users.

To configure it go to Setup > Manage Users > : you can add domains (e.g. or even subdomains (e.g. from now on every new or updated user's Email field must match the domain whitelist configure in this section.

Existing users' emails will still be valid till their update.

This restriction doesn't apply to external users (portal, Communities or Chatter, or simply every user that has a related Contact/Account).

More info here.

[Salesforce] The Sobject Crusade: AgentWork

Back to the Sobject Crusade list.

Source: AgentWork

This object represents work item assignment that has been routed to an Agent: this is basically a new type of queue management introduced with Summer 15 called Omni-Channel.

Omni-Channel is a comprehensive customer service solution that lets your call center route any type of incoming work item, including cases, chats, phone calls, or leads—to the most qualified, available agents in your organization.
Omni-Channel integrates seamlessly into the Salesforce console.

This release contains a beta version of Omni-Channel that is production quality but has known limitations (Summer 15).

To enable Omni-Channel go to Customize > Omni-Channel > Settings and flag Enable Omni-Channel.

Now let's create a Service Channel: this is the source of work items for the Omni-Channel, and can be associated to various standard objects and even custom object.

These objects are taken from queues and sent to the agent's console in real time.

To create a new Service Channel, click on Customize > Omni-Channel > Service Channels:

The Custom Console Footer Component field is optionally used to open a specific component on the Console when that specific work item is selected.

Next step is creating Routing Configurations, which determine how work items are routed to agents; click on Customize > Omni-Channel > Routing Configurations:


  • Routing Priority: is the priority of the current Service Channel. Other factors are counted when calculating the priority (available capacity of the agent, priority of the queue that the work item came from, amount of time that the work item has been waiting in the queue, members of the queue who are available to receive new work items from the queue). When an agent gets a work item, the owner of the object is set to the agent.
  • Routing Model: reflects the agent's behavior
  • Capacity Weight: amount of agent's capacity (set in the Capacity field of the presence configuration) scaled down when the work item is assigned. You can select a Capacity Weight or a Capacity Percentage, but not both.
  • Capacity Percentage: percent of agent's capacity scaled down when the work item is assigned

Now you can link your ORG queues to the Routing Configurations.

Click on Setup > Manage Users > Queues:

In the Routing Configuration set the configuration you have set up in the previous step.

Next step is to configure Agent's presence statuses: this way we can set up how much work every agent can handle.

When you enable the Omni-Channel feature Salesforce adds a Default Presence configuration to be applied to all Agent's by default.

Go to Customize > Omni-Channel > Presence Configurations and click the New:

You can set:

  • Capacity: maximum Agent's capacity
  • Automatically Accept Requests: automatically assigns a work item to an available agent
  • Allow Agents to Decline Requests: Agents can decline assignments; if "Automatically Accept Requests" is set to true, agents cannot decline
  • Update Status on Decline: update status when declining, only available if "Allow Agents to Decline Requests" is flagged

Finally one or more channels can be associated with different Presence Statuses, on Setup > Customise > Omni-Channel > Presence Statuses:
To assign Presence Statuses to users go to the User's Profile on the Enabled Service Presence Status Access and click edit:
This could be done as well using Permission Sets. Take a Case and set the Owner to be the previously created queue (so we can test it). Now configure the Cloud Console App (Setup > Apps > [YOUR_CONSOLE_APP_NAME]) to use the Omni-Channel component:
Now open the Console App (Developer Orgs come with a Sample Console app):
Go online by clicking on the presence status link to see the magic start:
You can change the object's compact layout (for Case go to Setup > Cases > Compact Layout) to show other informations of the object:
You can integrate with an already configured Live Agent. For more details read the official docs. Click "Accept" and the new AgentWork will be stored in the CRM:
select id,lastmodifieddate,CapacityPercentage,CapacityWeight,Name,OriginalQueue.Name,status,WorkItemId,ServiceChannelId,UserId from agentwork order by lastmodifieddate DESC

It shows all the Work Items assigned to the agents (this is basically the history of plyaing with a Case and looping over assigning to a queue and accepting/declining with the current User as Agent).

Tuesday, April 26, 2016

[Salesforce] The Sobject Crusade: ActivityHistory

Back to the Sobject Crusade list.

Source: ActivityHistory

The ActivityHistory object is a read-only object that shows all completed Tasks and past Events related to a give object (e.g. Account). It includes activities for all contacts related to the object.

This object is shown in the Activity History related list:

Few limitations apply:

  • The object cannot be queried directly but only queried through inner query (e.g. Select Id, (Select Subject From ActivityHistory) From Account Where Name = 'ACME bros')
  • Your main query must reference exactly 1 record
  • Inner query must not have a WHERE clause
  • Inner query must filter a maximum of 500 items

Here is an example query:
SELECT Name, (SELECT ActivityDate, Subject, IsTask FROM ActivityHistories ORDER BY ActivityDate ASC NULLS LAST Limit 500) FROM Account WHERE Name ='ACME Bros'

[Salesforce] The Sobject Crusade: AdditionalNumber

Back to the Sobject Crusade list.

Source: AdditionalNumber

This is an optional additional number for a call center, visible on the call center's phone directory: this is useful for numbers not releated to CRM objects (e.g. queues, conference rooms).

This seems boring, but continue reading to see some more action!

To create a new number, go to Setup > Customize > Call Center > Directory Numbers and click the New button:

The object can be optionally linked to a specific call center: if not set, this will be considered a global value (cross-call center valid).

Upon save you can query this object:

select Id, Name, Phone, Description, CallCenterId from AdditionalNumber

This is awesome, right?

Not at all!

Let's see how this is included in the overall Call Center configuration.

The Call Center configuration involves the configuration of a Computer Telephony Intgration, aka CTI.

As you can see in the picture above, CTI is an external service that communities with Salesforce: it is responsibile for handling phone (and other means, such as SMS or chat) communications and sending back to the CRM information about the call (e.g. calling number, duration of the call, origin, ...).

Here you can find the latest complete guide on CTI configuration. fortunately give developers a way to try this feature out without having to have access to real CTI hardware.

First download the CTI Demo Adapter from this link.

Once installed, you'll see the icon in the lower right corner of your desktop (sorry, MS Windows systems only); take the [installed dir]/DemoAdapter.xml file.

Now click on Setup > Customize > Call Center > Call Centers and click the Import button and import the previous XML file.

Click on Add user button to add new users (your current user at least).

Go to the Home page, you'll see a new component on the sidebar:

Wait till you see a new popup appearing (if it takes longer that a few seconds, click the button):

If you can't still see anything, it may be because of this kind of error while loading the CTI "localhost" service (see the CTI Adapter URL field on the Call Center setup page):

This happens because you are on an HTTPs site and trying to load an HTTP (less secure) content inside an iframe (don't worry it's not your fault!).

Click on the little shield on the addess bar (I'm using Chrome) and click on "Load Anyway" link on the popup that will appear (and reload the page).

Insert your Salesforce username/password to connect to the CTI:

Now the fake CTI adapter can trigger the following actions (right click on the adapter icon):

All this configuration to show where the AdditionalNumber object lays.

Click on the search button next to the textbox for dialing a number:

Select the number and watch it on the dial box:

Just for fun, let's take an Account and assign it the "4155551212" phone number:

This means that when the customer calls from this number, the CTI adapter will give Salesforce the calling phone number and redirects the user to the correct Account page. Let's click on the "Call From 415-555-1212" CTI Adapter action:

To watch Salesforce loading automagically the given Account page:

The sidebar shows additional infos for the Call Log, you can update as needed: this call will be saved in a Task object:

You can customize the Demo Adapter by changing the "demo_menu.xml" file (see more datails in the guide).

Friday, April 22, 2016

[Salesforce] The Sobject Crusade: ActionLinkTemplate

Back to the Sobject Crusade list.

Source: ActionLinkTemplate

Action Links has been presented when discussing the ActionLinkGroupTemplate object (see this object for a complete guide on configuring and using Action Links): they are a way to execute custom actions on button click on Chatter feed posts.

By templating an Action Link you define a template action which can be "instantiated".

The Action Link is defined by:

  • LinkType: this is the kind of action that you want to expose, and it can be:
    • Api: direct call to an API endpoint (with given method, parameters, headsrs)
    • Api Async: like the previous point but the server response is asyncrhonous: this way the serve have to send a response to /connect/action-links/[actionLinkId] endpoint to set the SuccessfulStatus o FailedStatus of the operation
    • Download: triggers a download of a file
    • Ui: redirects to the given URL
  • ActionUrl: endpoint of the action. This could have bindings values, e.g. "{!Bindings.customValue}&userId={!userId}"
  • Headers: headers request values (only for Api and ApiAsync), binding supported. Every header value should be in the form (one per line) "Header-key: value"
  • Method: HTTP method for the request, with the following supported behavior:
    • HttpDelete: HTTP 204 on success, response body is empty
    • HttpGet: HTTP 200 on success
    • HttpHead: HTTP 200 on success, response body is empty
    • HttpPatch: HTTP 200 on success or HTTP 204 if response body is empty
    • HttpPost: HTTP 201 on success or HTTP 204 if response body is empty
    • HttpPut: HTTP 200 on success or HTTP 204 if response body is empty
    "Ui" and "Download" types support only "HttpGet" value.
  • RequestBody: bpdy of the request (only for Api and ApiAsync), binding supported
  • LabelKey: standard set of labels (None if none apply, then use the Label field)
  • Label: custom label associated to the action (Pending, Success and Failed applied to the action action)
  • Position: position of the action in the defined group (0 is the first)
  • IsConfirmationRequired: users is prompted with a confirmation alert box upon click on the action
  • IsGroupDefault: default group action
  • UserVisibility: states who can see the action, that is Creator, Everyone, EveryoneButCreator, Manager (manager of the creator on the Action Link), CustomUser or CustomExcludedUser (using the UserAlias field to link to a specific user)
  • UserAlias: user alias to set the visibility of the action. Supports binding
  • LinkType:
  • LinkType:

You can query this object:

Select Id, ActionLinkGroupTemplate.DeveloperName, LinkType, ActionUrl, Headers, IsConfirmationRequired, Label, Method, RequestBody From ActionLinkTemplate

And get:

Tuesday, April 19, 2016

[Salesforce] The Sobject Crusade: ActionLinkGroupTemplate

Back to the Sobject Crusade list.

Source: ActionLinkGroupTemplate

Action Links are actions you can do in chatter posts (e.g. API call, document download, UI redirect) by clicking a button on the related chatter post.

Action Links are grouped into Action Link Group, so you can choose which action you want to play:

You may think that these actions comes to configuration and some sort of layout, but it is part configuration and part Chatter API call.

Action Links are grouped into Action Link Groups but this is not the object that will be configured.

In fact we talk about Templates (Action Link Group Template and Action Link Template): we define template actions rather than the actual actions we'll be executing.

The template defines the actions you want to apply to a Chatter feed: when you want to apply the group of actions to a feed, we'll make an API call to get the "instance" of the actions to be linked to the feed.

Let's start creating a Group Template (the object we are inspecting here) clicking on Setup > Create > Action Link Templates:

You can define:

  • Name and DeveloperName
  • Category (position of the action buttons in the feed)
  • Number of execution allowed
  • Hours untile the action expires

Once a group is published it cannot be modified anymore.

Let's query the object:

select id, DeveloperName, IsPublished, MasterLabel  from ActionLinkGroupTemplate

Let's define the actions:

With the following main fields (more details here):

  • Type of Action (API, API Async, UI, Download)
  • Endpoint of the action (in this example a simple request bin)
  • HTTP Method
  • HTTP Request Body
  • HTTP headers
  • Position among other buttons
  • Label (you can choose between some presets and a custom label)
  • Visibility

Consider that URL, request body and headers can have standard and custom binding values (you can for example pass the current User ID or a custom binding value).

These are the actions defined:

To use them we need a valid Session ID, a call to the /connect/action-link-group-definitions/ API endpoint and a call to Chatter API to send a feed.

We'll be doing things manually (we could use Workbench, but we like to get our hands dirty!).

First we get a valid OAuth Session ID.

Click on Setuo > Create > Apps click on New button in the Connected Apps section; we only need to setup the middle section:

to get access to Chatter API.

This is what you get:

This application will be online in 10 minutes at most.

Let's make a REST call to get a valid token using the OAuth Password Flow (details here ):

        Content-Type: application/x-www-form-urlencoded

The response returns the Session ID (athorization token) we'll use to get a valid Action Group Id from this REST call:

        Authorization: Bearer [SESSION_ID]
        Content-Type: application/json

Where templateId is the ID of the Action Link Group Template (you can query for it or get it in the configuration section of the template), and templateBindings is a list of objects (with "key" and "value" fields) for custom bindings.

This call will return an instance of the template:

  "actionLinks": [
      "actionUrl": "",
      "createdDate": "2015-08-14T20:41:42.566Z",
      "excludedUserId": null,
      "groupDefault": false,
      "headers": [
          "name": "content-type",
          "value": "application/json"
      "id": "0An240000004FSDCA2",
      "label": "Salute!",
      "labelKey": "None",
      "method": "HttpPost",
      "modifiedDate": "2015-08-14T20:41:42.566Z",
      "requestBody": "{"message": "Hello!", "from":"{!userId}"}",
      "requiresConfirmation": false,
      "templateId": "07l24000000GmbgAAC",
      "type": "Api",
      "userId": null
      "actionUrl": "",
      "createdDate": "2015-08-14T20:41:42.566Z",
      "excludedUserId": null,
      "groupDefault": false,
      "headers": [
          "name": "Content-Type",
          "value": "application/json"
      "id": "0An240000004FSECA2",
      "label": "Insult!",
      "labelKey": "None",
      "method": "HttpPost",
      "modifiedDate": "2015-08-14T20:41:42.566Z",
      "requestBody": "{"message":"Bad Word", "from":"{!userId}"}",
      "requiresConfirmation": true,
      "templateId": "07l24000000GmblAAC",
      "type": "Api",
      "userId": null
  "category": "Primary",
  "createdDate": "2015-08-14T20:41:42.566Z",
  "executionsAllowed": "Once",
  "expirationDate": null,
  "id": "0Ag240000004FSNCA2",
  "modifiedDate": "2015-08-14T20:41:42.566Z",
  "templateId": "07g24000000CaThAAK",
  "url": "/services/data/v34.0/connect/action-link-group-definitions/0Ag240000004FSNCA2"

Now we can use the id to post the action with a feed:

        Authorization: Bearer [SESSION_ID]
        Content-Type: application/json
          "body": {
            "messageSegments": [
                "type": "Text",
                "text": "What do you want to say me?"
          "subjectId": "me",
          "feedElementType": "FeedItem",
          "capabilities": {
            "associatedActions": {
              "actionLinkGroupIds": ["0AgRR0000004CTr0AM"]

Once you click on a button, the action is executed and no more action is possible:

The same sequence can be done using Apex and the ConnectApi library:

// Get the action link group template Id.
ActionLinkGroupTemplate template = [SELECT Id FROM ActionLinkGroupTemplate WHERE DeveloperName='Say_Hello'];

// Create ActionLinkTemplateBindingInput objects from the map elements.
List bindingInputs = new List();
// Add binding name-value pairs to a map: our action does not have custom bindings
Map bindingMap = new Map();
for (String key : bindingMap.keySet()) {
    ConnectApi.ActionLinkTemplateBindingInput bindingInput = new ConnectApi.ActionLinkTemplateBindingInput();
    bindingInput.key = key;
    bindingInput.value = bindingMap.get(key);

// Set the template Id and template binding values in the action link group definition.
ConnectApi.ActionLinkGroupDefinitionInput actionLinkGroupDefinitionInput = new ConnectApi.ActionLinkGroupDefinitionInput();
actionLinkGroupDefinitionInput.templateId =;
actionLinkGroupDefinitionInput.templateBindings = bindingInputs;

// Instantiate the action link group definition.
ConnectApi.ActionLinkGroupDefinition actionLinkGroupDefinition = 
ConnectApi.ActionLinks.createActionLinkGroupDefinition(Network.getNetworkId(), actionLinkGroupDefinitionInput);

This is what the bin has received:

Imagine you can use this feature for allowing selected users to partecipate to surveys/polls or make them doing actions to monitor their behavior.

Friday, April 15, 2016

[Salesforce] The Sobject Crusade: AccountTeamMember

Source: AccountTeamMember

The AccountTeamMember is the record that stores which Users are in the Account Team.

To enable Account Teams click on Setuo > Accounts > Account Teams:

Select which layouts will have the Account Team related lists:

You can now define the roles in your Account Teams:

I've added the Customer Support role and also added chart colors (for reports):

Let's go back to the Account and see the new Account Team related list:

Let's add a new Team:

The related list slightly changes:

By clicking the Display Access you also see the Account, Opportunity and Case access level for every user defined in the team.

The Add Default Team is related to the UserAccountTeamMember object that stores current User's default Account Team (users he works with ofter, it is a related list on the User's layout).

Let's query the AccountTeamMembers for the given account:

SELECT Id, Account.Name, User.Name, TeamMemberRole from AccountTeamMember where AccountId ='00124000005FoHP'

[Salesforce] The Sobject Crusade: AccountTerritoryAssignmentRuleItem

Source: AccountTerritoryAssignmentRuleItem

This object represents a row of selection criteria for an AccountTerritoryAssignmentRule object. AccountTerritoryAssignmentRuleItem can be created or deleted if the BooleanFilter field on its corresponding AccountTerritoryAssignmentRule object is a null value.

Unfortunately it is impossibile for me to show you how to use this object because I don't have a Salesforce ORG with the old Territory Management system, which allowed this kind of assignment rules.

For more details read the AccountTerritoryAssignmentRule blog post.

If you have an ORG with this kind of territory management enabled, feel free to write a simple guide on how this object work!

[Salesforce] The Sobject Crusade: AccountTerritorySharingRule

Back to the Sobject Crusade list.

Source: AccountTerritorySharingRule

Represents the rules for sharing an Account within a Territory.

Unfortunately it is impossibile for me to show you how to use this object because I don't have a Salesforce ORG with the old Territory Management system, which allowed this kind of assignment rules.

For more details read the AccountTerritoryAssignmentRule blog post.

If you have an ORG with this kind of territory management enabled, feel free to write a simple guide on how this object work!

[Salesforce] The Sobject Crusade: AccountTerritoryAssignmentRule

Back to the Sobject Crusade list.

Source: AccountTerritoryAssignmentRule

This is an Account assignment rule on territories based on Account fields: Winter '12 platform release added the new Enterprire Territory Management.

The following doc is a complete guide to setup Territory Management in your org.

This kind of Territory Management needs the Customizable Forecasts, that is an old version of the newest Collaborative Forecat feature, that's why it is not possibile to simulate a query on this object.

Read this documents:

"Territory Management is available only with Customizable Forecasts and not supported with the Winter ’12 release of Forecasts. If Territory Management is enabled, you can no longer use the Winter ’12 release of Forecasts."

This is a useful map that shows how object are related in Territory management.

If you have an ORG with this kind of territory management enabled, feel free to write a simple guide on how this object work!

Tuesday, April 12, 2016

[Salesforce] The Sobject Crusade: AccountTag

Back to the Sobject Crusade list.

Source: AccountTag

You can tag CRM objects. To enable this feature go to Setup > Customize > Tags > Tag Settings and click the Enable Personal Tags feature:

You can select all the object layouts in which you want to use tagging.

Now you can tag your account object:

Click on Add Tags:

Click Save:

These are Personal Tags, but you can also add Public Tags: to enable this feature, contact Salesforce support.

Once this is done you will have the Tag Manager permission on the profile page, that allow to use public tags that can be used org wide:

Once activated you can select the layout in which to enable Public Tags (edit layout and click on the Layout Properties button):

You can add the tags as you did for the Personal ones:

Let's query the AccountTag object:

select id, Type, Name From AccountTag Where ItemId = '0010000000assQ5'

YOu can enable the sidebar component for the tag search by clicking on Setup > Home > Home Page Layouts, edit your home page layout and select the Tag component:

This components outputs as:

Click on the Tag link of the sidebar component to browse tags: