Reacting to user feedback in a pet-project. Fast. – Telegram Group

Reacting to user feedback in a pet-project. Fast.

Initially, in my pet-project ROLLS, I implemented a default feedback mechanism — through user emails. Eventually, it became clear that reacting to such emails is very frustrating. Especially, when using a separate service email. The most annoying thing is when you don't react to the feedback fast enough, because of that it would probably be lost forever.

Also, since I was using Trello as my task tracking system — I wanted to create a task for every noteworthy feedback to react to it on time. For example, my application has a feature where you can submit your own content to the app. This type of feedback requires database modifications and usually can’t be dealt with in a moment.

Vague representation of my mailbox

The solution for me was to create a service that would work with the app’s database, Trello as my task tracking system, and Telegram as a messenger which is always open for me.

Sure, you can say that there are tons of similar solutions already. But most of them are bloated or expensive. The ones I found were Instabug, Canny, Usabilla, and others. And they were exactly that.

My small pet-project doesn't need bloated solutions and my monthly budget can hardly cover even the least expensive of them.

In the end, I implemented my own solution on a weekend and was pretty satisfied with it. That's why I decided to share it with the world.

Shortly, that's how it works:

  1. Application or website submits feedback to the Firebase.
  2. Node.js script listens to the new feedback submissions in the database and prepares human-readable feedback.
  3. The script creates a Trello card with the feedback and assigns it to the developer. Creating a Trello card helps to track old submissions and view their progress.
  4. Then the script sends a message to Telegram. The message contains buttons to open a Trello card related to the feedback or to open the user in Firebase. Sending a message helps react to submissions as fast as possible wherever you are.

How Does It Work

The work starts when the frontend sends a feedback object to the Firebase. The backend, at the same time, runs the Node.js script, which listens to new feedback submissions using the child_added Realtime Database callback.

reference.on('child_added', function(childSnapshot) {
const feedbackId = childSnapshot.key;
const feedbackValue = childSnapshot.val();
feedbackValue.id = feedbackId;
}

After receiving an object, the script starts preparing human-readable feedback that will be sent to Trello. To prepare it, the separate, text processor script (text_helper.js) creates card title and description, which contains user email, text, and system info.

function prepareTrelloRequest(feedbackValue) {
const cardName = textHelper.getPrettyFeedbackNameForType(
feedbackValue.feedbackType
);
const cardDescription = textHelper.getPrettyFeedbackDescription(
feedbackValue
);
sendTrelloRequest(feedbackValue, cardName, cardDescription);
}

Next, the Trello request gets sent. To assign yourself to the card change the idMembers value using process.env variables.

function sendTrelloRequest(
feedbackValue,
cardName,
cardDescription
) {
const query = {
key: process.env.TRELLO_API_KEY,
token: process.env.TRELLO_TOKEN,
name: cardName,
desc: cardDescription,
pos: "top", //Card will be placed on top of the list
idList: process.env.FEEDBACK_LIST_ID,
idMembers: process.env.ASSIGNEE_ID
}
const requestOptions = {
url: TRELLO_CREATE_CARD_URL,
qs: query
}
request.post(requestOptions, (err, res, body) => {
if (err || body.ok === false) {
return console.log(err);
}
const responseBody = JSON.parse(body);
prepareTelegramRequest(feedbackValue, cardDescription, responseBody.shortUrl);
})
}

After successfully making the request, we’ll need shortUrl inside Trello’s response. The URL is needed to create a button in a Telegram message.

Newly created Trello card. To track its progress I usually add a checklist inside.

Next, the script prepares a Telegram message using Trello’s response. The message gets created with action buttons — one that opens a Trello card, and another that opens a user who made a submission in Firebase.

function prepareTelegramRequest(
feedbackValue,
prettyFeedback,
trelloCardUrl
) {
const feedbackTitle = textHelper.getPrettyFeedbackNameForType(
feedbackValue.feedbackType
);
const textBody = `
New Feedback: ${feedbackTitle}
${prettyFeedback}`
const keyboard = createInlineKeyboard(feedbackValue, trelloCardUrl);
sendFeedbackToChannel(feedbackValue.id, textBody, keyboard);
}

Finally, the script sends the data to the Telegram channel. Note, that in request query parameters we use parse_mode=Markdown. It is required so the markdown formatting used in Trello, works in a Telegram message.

function sendFeedbackToChannel(feedbackId, prettyFeedback, keyboard) {
const botApiKey = process.env.TELEGRAM_BOT_API_KEY;
const chatId = process.env.TELEGRAM_CHAT_ID;const url = `https://api.telegram.org/bot${botApiKey}/sendMessage?chat_id=${chatId}&text=${prettyFeedback}&parse_mode=Markdown&reply_markup=${keyboard}`
const encoded = encodeURI(url);
console.log(url);
request(encoded, {
json: true
}, (err, res, body) => {
if (err || body.ok === false) {
return console.log(err);
}
processedFeedbackLogger.write(`${feedbackId}\\n`);
});
}

In the end, the message would look like this:

Nice, huh?

Multiple Firebase callback problem

There is one problem with that Firebase child_added callback — during the initial startup of the script, it fires events for every feedback in the database. My solution to this problem was a simple method that writes all submitted feedback id’s to the .txt file and when the new feedback arrives — checks if the file contains a new feedback id.

Another valid solution would be to remove the feedback in Firebase after it was processed.

// After receiving an event in ref.on('child_added',...)
const feedbackId = childSnapshot.key;
if (processedFeedbackIds.includes(feedbackId)) {
console.log("This feedback was already logged");
return;
}
............
// After receiving a successfull response from Telegram
processedFeedbackLogger.write(`${feedbackId}\\n`);

Getting the Environment Variables

To make this all work you need to specify the environment variables in the .env file in the project’s root folder.

Firebase Service Key

To work with Firebase Realtime Database using the script you’ll need a Firebase service key. I won’t go into the details and just link the official documentation here. After receiving service key .json — put it into the project root folder.

Realtime Database setup

If you are reading this article, you probably already have the Firebase project and Realtime Database or Firestore set up.

For FIREBASE_DATABASE_URL you’ll need your database base URL. It looks something like this: https://<project-id>.firebaseio.com/. For FIREBASE_FEEDBACK_REFERENCE and FIREBASE_USERS_REFERENCE you’ll need your feedback and users reference inside the database. In my case, it was feedback_v1 and users.

FIREBASE_DATABASE_URL='Realtime Database base url'
FIREBASE_FEEDBACK_REFERENCE='Feedback List Reference'
FIREBASE_USERS_REFERENCE='User List Reference'

Trello setup

For Trello to work you’ll first need the token and the API key. You can get the key on the Trello API key page. You can get the token on the same page.

Getting the list and assignee id is a bit trickier. The easiest way to get them is to:

  1. Create a card in your Trello board
  2. Open the card
  3. Add .json to the page URL
  4. Get the idList and the first element of idMembers list.
That's how your URL should look like
TRELLO_TOKEN='Trello token'
TRELLO_API_KEY='Trello API key'
FEEDBACK_LIST_ID='List Id to add feedback card'
ASSIGNEE_ID='User Id of the assignee'

Telegram setup

First, you need to set up a bot, that will send feedback messages to the channel. I won’t go through all the steps required to create a bot and will just link official documentation.

After creating a bot, the BotFather will send you an API key of the bot. That one will go to TELEGRAM_BOT_API_KEY.

Next, you’ll need to create a channel, make the bot its admin, and get the channel id. There are multiple ways to get the channel id. I'll go through the easiest one. Copy the link to any of the channel’s messages, for example, https://t.me/c/1/20. The 1 in the link is the channel’s id and 20 is the message’s id. Specify your id in TELEGRAM_CHAT_ID.

You can also use this method either for channels or chats.

TELEGRAM_BOT_API_KEY='Telegram bot API key'
TELEGRAM_CHAT_ID=-'Telegram channel or group id'

Conclusion

In the end, this solution helped me decrease the response time to new feedback to less than 5 minutes. Users get their questions answered faster and I, create tasks from their feedback and quickly implement them.

Of course, you can change the technical stack I am using to your own solutions. Firebase can be replaced with your own backend, Trello can be replaced with your own task tracking system, and Telegram can be replaced with any messenger of your liking.

Check out and star the source code on Github:

dyckster/Feedback-Reactor

Rapid feedback checker for Firebase + Trello + Telegram GitHub is home to over 50 million developers working together…

github.com

And don’t forget to give claps and leave comments 🙂

Cheers.

Ten articles before and after

XiongMai IP Camera Motion Detection Alert Snapshot to Telegram Bot – Telegram Group

On-The-Go Tools for Foreign Flow Analysis – Telegram Group

What is uniREAP ?. What is Staking ? – Telegram Group

HOW TO DEPLOY RUBY BOT LIVE ON HEROKU – Telegram Group

Using Google Scripts and Telegram BOT to make my personal budget App – Telegram Group

Telegram bot on the cloud. I wanted to create a bot in Telegram… – Telegram Group

data-rh=”true”>Explainer: UK News Quiz, a Telegram Bot – Dror Kessler – Medium – Telegram Group

How to send photos to Telegram in Ruby – Telegram Group

Telegram’da Benim de Bir Tuzum Olsun – Telegram Group

Controlling Light using Telegram Bot – Telegram Group