As a Salesforce developer, you don’t limit yourself to only coding. Also, you have to create and manage lots of Salesforce notifications. It is helpful to gather notifications in one place to streamline processes and be aware of the situation. It would be even great if each team could receive specific notification types.
For example, the Sales team can receive notifications about opportunities changes, while the dev team can receive error alerts in real-time to quickly eliminate the person who crashed the prod 🙂.
At ENWAY, we use Slack as our corporate messenger and notification hub. Not only is it a part of the Salesforce ecosystem, but also a messenger with vast integration capabilities.
In this article, you will find a ready-to-use guide on how to send Salesforce notifications to Slack channels via webhook technology. So, sit comfortably and embark on reading!
STEP 1: Create Slack App and
Config Webhook
Let’s start from the foundation: click here to start a Slack app creation. Pick its name, choose a workspace, and then click Create App. Also, you can use the app that was created previously.
From the Settings page, select the Incoming Webhooks feature, and click the Activate Incoming Webhooks toggle.
Why Do We Use Webhooks?
Incoming webhooks provide an easy way to share information from external sources with your workspace. So, they provide a simple mechanism for posting a message without managing the state or handling authentication credentials.
How It Works
- Configure an incoming webhook to send data to a specific channel.
- Format webhook messages to stand out from other alerts in the channel.
- Send HTTP requests with a JSON payload which includes the message’s text and other variables.
Incoming webhooks allow you to add context to your messages by attaching helpful content and links. Things like images, websites, or other pieces of data make these messages more useful for your team. You can also take a step further and add Block Kit formatting to your message!
Key Limitations
- Incoming webhooks can only post to a single Slack channel that you picked up during the app creation. To bypass it, check chat.postMessage Web API. This method allows your app to post into any channel it has access to and provides a more straightforward way to reply to threads.
- You have to be a member of a private channel to post to it.
- Incoming webhooks can’t get responses to the messages they post or process responses from interactive elements (buttons etc.). They serve only notification purposes.
With the Incoming Webhooks enabled, the settings page will refresh. You should find and click the new button named Add New Webhook to Workspace.
Voilà, no code is needed! As a result, you will see a similar screen:
Go ahead and pick a channel that the app will post to, and then click to Allow your app. Just a friendly reminder, If you want to add Incoming Webhook to a private channel, you must be a member of this channel.
You’ll be redirected back to the settings, where you will find a new entry under the Webhook URLs for Your Workspace section. Look for a similar URL:
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
This URL is your Incoming Webhook – which means that we’ve successfully finished step 1.
Please note that your webhook URL contains secret information and is specific to a single user and channel. Don’t share it.
STEP 2: Prepare Your Salesforce Environment
If you’ve created the Slack app, you are halfway to success. For step 2, I’ve prepared a simple template for sending notifications from Salesforce. You can send notifications using:
- Apex classes,
- LWS components,
- Invocable method in the Flows.
Just below, you can see the sample of the code that allows you to activate the payload:
@InvocableMethod(Label='Send notification in your Slack workspace' Category='Messaging')
public static void sendNotification (List<MessageParam> messageParamsList) {
generateJson(messageParamsList);
sendRequest(body);
}
@AuraEnabled
public static void sendNotification (MessageParam messageParam) {
generateJson(new List<SlackNotifier.MessageParam>{messageParam});
sendRequest(body);
}
public class MessageParam {
@InvocableVariable(Required=true Label='Enter you message')
public String textMessage;
@InvocableVariable(
Required=true
Label='Choose notification type'
Description='Fatal;Info'
)
public String messageType;
public String className;
}
When you are preparing a request, remember to store the endpoint outside the code. I recommend you use Custom Settings (for example, Web Services) for storing the endpoint that you received when creating an application in Slack.
@Future(Callout = true)
private static void sendRequest(String body){
HttpRequest request = new HttpRequest();
Web_Services__c webServices = Web_Services__c.getValues('Slack');
// avoid saving endpoint in variable, this is link for you slack workspace
// everyone who have endpoint can send message
request.setEndpoint(webServices.Endpoint__c);
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setBody(body);
Http http = new Http();
http.send(request);
}
The notification text should be in JSON format as the body of an application/json POST request. To create a message, I used an Apex class with constants for ease of use:
// slack notifier constants
public static final String DIVIDER_BLOCK = 'Divider';
public static final String FATAL_BLOCK = 'Fatal';
public static final String TEXT_BLOCK = 'Text';
public static final String INFO_BLOCK = 'Info';
public static final String HEADER_BLOCK = 'Header';
public static final String TIME_BLOCK = 'TIME';
public static final String START_JSON = 'Start';
public static final String END_JSON = 'End';
public static final String EMPTY_STRING = ' ';
public static final String COMMA = ',';
public static Map<String, String> returnJsonBlock (String textMessage) {
textMessage = textMessage.replaceAll('"', '\"');
Map<String, String> jsonBlockMap = new Map{
HEADER_BLOCK => '{"type": "header", "text": {"type": "plain_text", "text":' +
'"Salesforce notification"}},{"type": "divider"}',
DIVIDER_BLOCK => '{"type": "divider"}',
TIME_BLOCK => '{"type": "section","text": {"type": "mrkdwn","text": ' +
'":calendar: *UPCOMING EVENTS* "}},' + '{"type": "section","text":' +
'{"type": "mrkdwn","text": "' + Datetime.now().format() + '"}}',
FATAL_BLOCK => '{"type": "section","text": {"type": "mrkdwn","text": ' +
'":warning: *You received a fatal notification:*"}}',
TEXT_BLOCK => '{"type": "section","text": { "type": "mrkdwn","text": ' +
'"' + textMessage + '"}}',
INFO_BLOCK => '{"type": "section","text": {"type": "mrkdwn","text": ' +
'":information_source: *You received a notification:*"}}',
START_JSON => '{"blocks": [',
END_JSON => ']}'
};
return jsonBlockMap;
}
Your notifications can have a visual effect and be more colorful – there is no limit to the fantasy. You can practice with Block Kit Builder and generate the desirable message format. In the sample below, I have generated the Post body:
private static void generateJson(List messageParamsList) {
Map<String, String> emptyBlockMap = ApexConstants.
returnJsonBlock(ApexConstants.EMPTY_STRING);
body = emptyBlockMap.get(ApexConstants.START_JSON);
body += emptyBlockMap.get(ApexConstants.HEADER_BLOCK);
body += ApexConstants.COMMA;
body += emptyBlockMap.get(ApexConstants.TIME_BLOCK);
body += ApexConstants.COMMA;
for (MessageParam messageParam : messageParamsList){
Map<String, String> jsonBlockMap = ApexConstants.
returnJsonBlock(messageParam.textMessage);
if (String.isNotBlank(messageParam.className)) {
String textMessage = ApexConstants.ORIGINATED_FROM + messageParam.className;
body += ApexConstants.returnJsonBlock(textMessage).
get(ApexConstants.TEXT_BLOCK) + ApexConstants.COMMA;
}
String messageType = jsonBlockMap.containsKey(messageParam.messageType) ?
messageParam.messageType :
ApexConstants.INFO_BLOCK;
body += jsonBlockMap.get(messageType);
body += ApexConstants.COMMA;
body += jsonBlockMap.get(ApexConstants.TEXT_BLOCK);
body += ApexConstants.COMMA;
body += jsonBlockMap.get(ApexConstants.DIVIDER_BLOCK);
body += ApexConstants.COMMA;
}
body = body.removeEnd(ApexConstants.COMMA);
body += emptyBlockMap.get(ApexConstants.END_JSON);
}
If you have done everything correctly, you will receive the amazing notification:
Final Thoughts
In conclusion, I want to emphasize that Salesforce notifications in Slack are a simple yet reliable way to instantly notify people about important events across your company.
This approach can be extended almost limitlessly. For instance, you can:
- send specific Salesforce notifications to only specific Slack channels,
- send monthly sales summaries to the heads of departments in a direct message,
- remind employees about birthdays 🎉 ,
- or even choose meals for team buildings 🥩!