Custom Slack Integration
If you are looking for the official Slack integration check here
This article will walk you through creating a custom Slack integration for your ABsmartly Web Console. The integration will be a NodeJS Express app that sends notifications about experiment events to a Slack channel of your choice.
📌 Example: Check out a starter integration on our examples GitHub repository.
Prerequisites​
- NodeJS (v14+)
- npm (v6+)
- Git
- ABsmartly Web Console account with admin access
Create a Node Project​
First, we will create a new NodeJS project using npm. In your terminal, run:
mkdir absmartly-slack-integration
cd absmartly-slack-integration
npm init -y
Install dependencies​
Next, we will install the dependencies we need for our express app:
npm i express body-parser dotenv axios
npm i -D typescript ts-node nodemon @types/node @types/express @types/body-parser @types/axios
and create a tsconfig.json
file:
npx tsconfig.json # Choose node
Inside your tsconfig.json
, add a rootDir
compiler option, like so:
{
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
...
}
}
Create Initial Express App​
Create a src
folder and add an index.ts
file:
mkdir src
touch src/index.ts
Inside the index.ts
file we will start with a simple Express app.
import express from 'express';
import bodyParser from 'body-parser';
import "dotenv/config";
const PORT = process.env.PORT || 3000;
const app = express();
app.use(bodyParser.json());
app.post('/', (req, res) => {
console.log(req.body);
res.status(200).send("OK");
})
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
})
This code simply listens on port 3000 and logs the body of any POST request to the console. To run it, let's add some
scripts to our package.json
file:
{
...
"scripts": {
"build": "rm -rf dist && tsc",
"start": "node dist/index.js",
"dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"
},
...
}
Now we can run our express app with npm run dev
and in a separate terminal window, send a POST request to it:
curl -X POST -H "Content-Type: application/json" -d '{"message":"Hello World!"}' http://localhost:3000
You should see the message logged in the terminal window where the express app is running.
Create a Slack App​
To hook up our express app to Slack, we will need to create a Slack App that can accept incoming webhooks. A tutorial for how to set this up can be found here.
Once you have a Slack Webhook URL, we can continue with the guide!
Sending a Message to Slack​
Create a .env
file and add your Slack Webhook URL to it:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX
We will now send a message to Slack to make sure everything is working. Add the following code to
the top of your index.ts
file:
const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL || "";
const postToSlack = async (message: Record<string, unknown>) => {
return await axios.post(SLACK_WEBHOOK_URL, message);
};
and change your app.listen()
function to:
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
postToSlack({
text: "Hello from the ABsmartly Slack integration!",
});
});
Start your app with:
npm run dev
And you should see a message appear in your Slack channel!
Commit Your Changes​
To deploy our Express app, we will be using Render.com. The simplest way to get started is to create a repo on GitHub and push our code to it.
First, go to https://github.com/new and create a new repository, then follow the instructions to push your code:
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_GITHUB_REPO_NAME>.git
git branch -M main
git push -u origin main
Deploying Your Express App​
Now our code is online, we can deploy our initial Express app. For this guide we will be using the free service, Render.com, but feel free to use any service that you like!
Setting up Render​
Create a render account and create a new web service. Choose NodeJS as the type, connect your Github account and select your repository from the list.
For the build script, input
npm install && npm run build
and for the start command:
npm start
Click on Save and your express app should start building and deploying, but you won't receive a message in Slack yet.
First, head to your render service's settings and click on the Environment tab. Add your Slack webhook URL as an environment variable.
Make sure to have the same name as in your .env
file, SLACK_WEBHOOK_URL
.
Render should automatically redeploy your app with the new environment variable and a message should appear in your Slack channel.
Creating a Webhook in ABsmartly​
Now that we have our express app deployed, we can create a webhook in ABsmartly.
Go to https://your-company-name.absmartly.com/settings/webhooks and create a new webhook.
For the name, enter Slack Integration
and for the URL, enter the URL of your express app https://your-service.onrender.com.
We are going to make sure our webhook is Enabled
and Ordered
; we will give it 3 max retries;
and we will choose to send events whenever any experiment event occurs.
This includes:
- ExperimentCreated
- ExperimentDevelopment
- ExperimentStarted
- ExperimentStopped
- ExperimentRestarted
- ExperimentFullOn
- ExperimentEdited
- ExperimentCommented
- ExperimentArchived
- ExperimentUnarchived
- ExperimentAlertCreated
Click Create Webhook
and we should start receiving events in our express app!
Sending ABsmartly Events to Slack​
Our app is now receiving events from ABsmartly, but we are only running console.log()
on the event data
(have a look at your Render logs to see this in action).
Let's send these events to Slack!
In your index.ts file, add the following function:
const handleEvent = (event: Record<string, unknown>) => {
console.log(event);
const eventName = event.event_name as string;
postToSlack({
text: `Event: ${eventName}`,
})
}
and change your app.post()
function to:
app.post("/", async (req, res) => {
try {
req.body.events.forEach(handleEvent);
} catch (error) {
console.error(error);
}
res.status(200).send("OK");
});
Don't forget to remove your test message from the app.listen()
function!
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
Now, whenever an experiment is changed or has an alert created, that event will be sent as a message to your Slack channel!
For further formatting of the messages, checkout the various Webhook Payloads that ABsmartly can send, and have a look at Slack's Message Formatting documentation.
Our final index.ts
file should look like this:
import express from "express";
import bodyParser from "body-parser";
import axios from "axios";
import "dotenv/config";
const PORT = process.env.PORT || 3000;
const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL || "";
const app = express();
app.use(bodyParser.json());
const postToSlack = async (message: Record<string, unknown>) => {
return await axios.post(SLACK_WEBHOOK_URL, message);
};
const handleEvent = (event: Record<string, unknown>) => {
console.log(event);
const eventName = event.event_name as string;
postToSlack({
text: `Event: ${eventName}`,
});
};
app.post("/", async (req, res) => {
try {
req.body.events.forEach(handleEvent);
} catch (error) {
console.error(error);
}
res.status(200).send("OK");
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
Next Steps​
Our example Slack integration repo goes quite a bit further by pulling experiment and user data from both the ABsmartly Web Console and the Slack API to enrich the messages that are being sent. Feel free to fork it and use it as a starting point for your own integration!