The Intercom Tag Enforcer

The Why

Since I’ve joined ReadMe, I’ve run into a wide range of support conversations, from invoice requests, to customers sending us selfies. Being on the support team, I had a good idea of the kinds of conversations we were having with our customers, but I wanted to go a step further and have quantifiable data that would show us how ReadMe is evolving. This is where Intercom Tags came in.

The thing with tags is, if you haven’t built the muscle, they're easily forgotten. Sure you can write rules to auto-tag conversations via the operator, but some conversations are bound to slip through the cracks.

The How

With that in mind, I turned to the Intercom API to implement an enforcer that would yell at us every time we tried to close a conversation without tagging it!

The first thing we did was set up a webhook to send a post request to our endpoint on conversation close. Setting up the webhook was pretty simple thanks to Intercom's great documentation. 😉

Once conversation data was sent, the rest was simple! We would then check if there were any conversations. If there weren't, the conversation would be re-opened and re-assigned with a note added; if there were, the conversation would be closed as normal!

Since Then

Since we've implemented this, here are some of the types of conversations we've been having (data is from 11/1 - 11/30):

Tag # of Convos
Billing 65
Cloudflare Migration 34
Invoice Request 29
Swagger Related Issues 27
Security Research 26
API Explorer 26
Dash Functionality 20
Delete Account 19
Open Source Requests 15

With this in place, we're looking forward to seeing all the data on what our customers are inquiring about or where they're getting confused, so we can improve our knowledge base!

const Intercom = require('intercom-client');
const intercomClient = new Intercom.Client({ token: intercomKey });

router.post('/webhook', (req, res) => {
  const conversationId = req.body.data.item.id;
  const assigneeId = req.body.data.item.assignee.id || 0;

  intercomClient.conversations.find({ id: conversationId }, conversation => {
    const tag = conversation.body.tags.tags;

    if (!tag.length) {
      const noteData = {
        id: conversationId,
        type: 'admin',
        message_type: 'note',
        admin_id: intercomAdminId,
        body: 'Please tag the conversation! :)',
        assignee_id: assigneeId,
      };

      intercomClient.conversations.reply(noteData, result => {
        if (result) {
          const openData = {
            id: conversationId,
            type: 'admin',
            message_type: 'open',
            admin_id: intercomAdminId,
            assignee_id: assigneeId,
          };

          intercomClient.conversations.reply(openData, () => {
            res.status(200).send({ msg: 'Note added and conversation re-opened!' });
          });
        } else {
          res.status(404).send({ error: 'Conversation not found' });
        }
      });
    }
  });
});