Why & how we built a Slack app for Amplitude
If your team is anything like ours, you’re in Slack…a lot. At Amplitude, almost all internal communication happens in Slack, and it’s even our preferred method for talking to some of our customers.
Which is why when we were thinking about how to help teams share and discuss insights from user data, Slack was the first thing that popped into our minds. In fact, lots of our customers told us that they were taking screenshots of Amplitude graphs and pasting them into Slack for further discussion — not exactly an ideal workflow.
A couple months ago, we announced the beta of Amplitude 2.0, and we officially launched 2.0 to all of our users last week. Our mission as a company is to help businesses understand their users so that they can build better products. And the driving force behind Amplitude 2.0 was to make analytics approachable to anyone, regardless of analytics experience, so that everyone on a team can access, explore, and learn from their user behavior data.
When it comes to helping teams build better products, a big part of that is figuring out how we can help them communicate more effectively and efficiently about data, so that they can make better and faster decisions. That’s why, in addition to a visual overhaul, improved chart usability, and better collaboration features, we added a Slack integration in 2.0.
In this post, I’ll go over some of the decisions we made as we developed the integration, as well as show off some of the ways we’ve been able to take advantage of Slack’s APIs to make a really useful integration for our customers.
Why a Slack app?
One of the things that Slack does very well is that it unfurls links that are shared in messages. Slackbot will crawl the shared page and fetch metadata to generate a nice preview for the link. There is a slight hitch, however, when you try to share an Amplitude url in Slack. Because all of our dashboards, charts and tabs require authentication, the Slackbot is unable to fetch any useful metadata, resulting in this rather useless preview:
Our solution was to build an Amplitude Slack integration, where users can connect their Slack team and grant permissions to Amplitude. The integration provides an Amplitude bot, which can then be invited into channels and group messages in Slack.
When the bot detects that an Amplitude 2.0 link has been shared by a connected user, it can verify that user’s credentials in Amplitude, and post back metadata to generate a proper preview. The Slack integration aligns very closely with our central theme of improving accessibility to analytics and providing better tools to help users gain insights from their data.
Connecting Amplitude to Slack
Connecting Amplitude to Slack is very easy. After logging into Amplitude 2.0, just open the settings drop down in the top right corner and click “Connect to Slack”. After you click “Connect to Slack”, you will be prompted to install the Amplitude Slack integration and authorize the Amplitude bot. All users that want their links to be unfurled by the Amplitude bot must perform this step.
This process initiates Add-to-Slack OAuth flow, which allows us to link your Slack credentials to your Amplitude account. Slack will first verify that you have permission to install the Amplitude app to your Slack Team, and then redirect you to Amplitude’s Slack-OAuth endpoint to complete the flow. One of the post parameters in the redirect will be a code, which we can use to fetch your Slack user_id, team_id, and an access_token from Slack.
Since you are already logged into Amplitude, we can then link your Slack credentials to your Amplitude account. This mapping from Slack user_id to Amplitude user_id is very important since shared links detected by the Amplitude bot will only provide the Slack user_id. We need to look up the corresponding Amplitude user and verify that they have read permissions and org access for the shared link before posting all of the metadata.
After connecting and installing the Amplitude integration, you can simply do /invite @amplitude to invite the bot into any of your team channels to have it start unfurling your Amplitude links. You can also invite it to group messages, and you can even send direct messages to the bot as well.
How it works
Now that the Amplitude bot is integrated and invited to team channels and chats, it will begin to listen for messages containing Amplitude links. Slack’s Events API allows the Amplitude bot to subscribe to messages sent in channels and chats that it is invited to, and our bot endpoint will receive a notification for every message. Each notification contains the Slack user id, team id, channel id, the message text, and a challenge token. As a requirement, our bot endpoint must reply to the notification with the challenge token as the body within 3 seconds.
The bot receives notifications for all messages, including messages that do not contain Amplitude links, and so the first step when processing the notifications is to filter out all messages that do not contain an Amplitude link, as well as messages sent by users that have not yet connected their Slack account to Amplitude. Next we look up the Amplitude user from the Slack user_id, determine the link type using regex expressions, and verify that the user has read access to that specific chart, dashboard, or cohort.
Lastly, we load the metadata for the dashboard, cohort, or chart, and formulate a Slack message JSON blob to post back into the channel as the Amplitude bot, using Slack’s Message API. The Message API offers a lot of control over the message display format, allowing us to neatly display the metadata. If the shared link is a chart object, we will also render a PNG preview (using the same “Export as PNG” logic available in Amplitude), and upload it as file. Uploading straight to Slack is a great option since the file is hosted by Slack, and Slack automatically obfuscates the URLs as a security measure. Clicking on the image preview will then expand it in the Slack client:
Depending on what kind of Amplitude 2.0 link is shared, different previews and message buttons will appear. For shared cohort links the bot will provide useful information such as the current user count and when that count was last updated.
For shared chart links, the bot will show the creator of the chart, the project it belongs to, the date range of the data, as well as an actual image preview.
Using Slack’s message buttons for Dashboard functions
You may have noticed that the chart previews all have an “Add to Dashboard” button. One of Amplitude 2.0’s major improvements is a new data model that allows users to more easily create, duplicate, share, and discover dashboards and charts. For example, users can create a dashboard with charts tracking each of their team’s core KPIs. When they share the dashboard with their team, other members can pin it to their sidebar in Amplitude for easy access.
The Amplitude Slack integration helps to expose these actions via message buttons in the previews. Those users can now pin the shared dashboard to their Amplitude sidebar directly from Slack by clicking on the message button.
The message buttons are a cool feature of Slack’s Message API. You can add the buttons as actions in your message attachment. For each button you can specify the display text, a name, a value, and a callback id. Similar to the Events API, when a user clicks on one of these Amplitude message buttons, we will receive a notification at our interaction endpoint. The notification will again contain the Slack user id, team id, channel id, as well as the callback id, action name, and action value.
From the callback id and action name, we can determine which behavior the user wants to trigger. The action value is also useful for passing some state information. For example we JSON encode some metadata such as the chart id and dashboard id in the action value. Our interaction endpoint then decodes the metadata and uses it to execute the action behavior.
After performing the action, our interaction endpoint will then respond directly to the notification with an ephemeral message to indicate success or failure or to provide more interactions. For example after we successfully pin a dashboard to a user’s sidebar, we post back this message:
For shared chart links, the available action is “Add to Dashboard”. When a user clicks on that we also need to determine which dashboard they want to add the chart to, and so we will post back a message containing up to 5 of their most recent dashboards as additional buttons (Slack currently only allows up to 5 buttons per message). Clicking on one of the dashboard names completes the chart interaction flow.
It’s important to note that our response messages are all ephemeral, meaning they are only visible to the user that invokes the action. That way each user can interact independently with the shared links. User A won’t see User B’s dashboards when User B clicks on “Add to Dashboard” and so on. The interaction API also allows you to post messages visible to everyone, or even directly update the original message (the one with the message button), which might be useful if you want to notify the team or coordinate interactions between users.
We’re very excited to share the Amplitude Slack app with our users, and as we continue to build out more features for Amplitude 2.0, we plan to incorporate many of them into our Slack integration. Potentially we could see things like notifications and reports coming to our Slack app.
(If you need help at any point with the integration you can also send our bot a direct message that says “help”, and our bot will reply with instructions for setting up and using the integration. You can also check out the full documentation here)
None of this would be possible without Slack’s APIs, which are flexible and yet sophisticated enough to allow us to implement the interactions exactly as we have envisioned them. I also just want to thank Slack’s Platform team for all the help and support they’ve provided us while building the integration!