Building feedback loops with your SaaS customers is a hidden goldmine. Yet very few product seem to grasp the importance of feedback, and even fewer seem to ask for feedback from their most engaged people the right time.
User feedback is a sensitive topic. It must be seamless for your users to talk with you, especially when they have an urgent problem. Otheriwse this leads to unsatisfied people and their annoyance might lead to public rants.
In this post, I want to highlight the process of building an in-app power user feedback form for BrandBird studio.
Why Power User Feedback Is Important
User feedback is vital to a SaaS's well-being. Either good or bad, feedback provides insights into how users use your product and whether you have any urgent (or minor) bugs.
That’s why it’s so important to set up a proper feedback loop in your SaaS. And the key “secret” is to make it dead simple for users to reach out to you.
Feedback from power users is even more important since these people are fueling your SaaS’s success. You have to listen to them and always define your strategy based on their needs.
Power User Definition
For BrandBird, we use Mixapanel to gather product usage analytics. Among many metrics, we store the number of user exports—how many times a user downloads or copies their design to the clipboard.
It’s the BrandBird north star metric, and it’s crucial to measure it in a specific timeframe. The timeframe is highly objective and it varies from product to product. The best way to come up with the right timeframe is to look at your insights and ask your customers how often they use your product or simple intuition.
For our case, it made sense to search for users with 30 or more exports within the last 30 days.
Feedback Frequency
How often should we ask our power users for feedback? It’s a simple yet very complex question.
You can ask them once, or you can ask them in a fixed interval.
I decided to ask for feedback multiple times. The product evolves daily and it makes sense to establish a continuous feedback loop with your most precious users.
In our case, we ask them again 6 months after their last feedback submission. Twice a year, a reasonable timeframe.
Of course, the user must meet the power user criteria after 6 months too.
Actual Feedback Questions
It’s another great question that you should ask yourself and honestly I’m not sure what’s the right answer.
You can show a simple NPS survey, ask simple one-click questions, free-text questions , etc. Literally there’re infinite choices.
For my case, I went with the free-text questions only because I want to get the unbiased users opinions.
It makes sense to test different content and see what kind of questions perform better for your case.
Your goal is to hear useful insights (good or bad) about your product. It’s not to hear that your product is perfect.
Architecture
Now that I had established the requirements, it was time to figure out the best way to actually build this functionality.
Below I’ll share the algorithm that I decided to follow and then I’ll share more in-depth details about the tech choices for both the backend and the frontend part.
- I’ve created an endpoint that loops over all our users and extracts those who meet the power user definition – 30 exports within the last 30 days and no feedback submission for the last 6 months. For the users that meet the rule, I set the showFeedback user profile attribute to true.
- Set up a cron job that sends a GET endpoint to the endpoint every Monday. It’s a waste of computing resources to make the calculation more often.
- On the frontend, I show the feedback form element only for those who have the showFeedback attribute enabled. Also, it’s possible for the user to close the form to avoid distraction in the app.
- Save form submissions on the database because I want to know who has responded and send me an email with the submission.
Finding the best way to build the feedback form in-app took me a while. I ended up with this process:
- Create a backend endpoint that finds all the users who fit the power user criteria (more than 30 exports last month, no feedback response within the last 3 months) and then update their user profile by setting the showFeedback attribute to true.
- Set up a corn job every Monday to calculate current power users.
- On the frontend side, it’s not as simple as reading the showFeedback property. I have to allow users to temporarily close the form widget. That’s when they close the form, I don’t update the backend showFeedback attribute, but I set a cookie delayFeedbackDate with a timestamp in the future (eg. one week from today). The rule that I use to show the feedback is: showFeedback is true and today is after the delayFeedbackDate.
- Gathering the responses was another issue. I need to know if the user has already responded to avoid showing the form repeatedly. That’s why I had to create a table for feedback responses. With MongoDB and claude.ai help that was pretty straightforward.x
Backend Implementation
The BrandBird backend is built on Express.js and Mongoose. The power user endpoint is a regular Express route and I’ve used a super complex MongoDB query to get power users with a single query. Hopefully, I’ve used Claude.ai for the complex aggregation.
Since I needed to know when and who responds to the feedback, I had to create a Feedback schema to save all the submissions and a POST route to save new feedback submission.
For each submission, I forward the response to my email so I can reply to the user as soon as possible. I use the SendGrid API for sending the email, but you can use any other email API.
Frontend Implementation
The frontend side had its challenges as well.
For the actual UI, I’ve chosen a subtle intro animation to the bottom right corner of the main BrandBird editor. Intentionally, I delay the intro animation for a few seconds to make sure the popup will capture the user’s attention. The animation is build with Framer-motion, my favorite React animation tool lately.
[INTRO ANIMATION HERE]
The complex part was the close functionality. It’s totally understandable that the user might not want or have time to share their feedback, so I placed a close icon. When the user clicks the close button, you have two options:
- Never show again the feedback popup
- Delay the popup for a few days and show it again.
The whole reasoning behind the feedback widget is that power users want to make your product better too. Not for your sake, but to make their own life easier. Then, you can assume that it’s okay to ask for their feedback.
Then, I decided to pick the second option and delay the popup appearance for 7 days in case the timing was off for the initial nudge.
I’ve used a browser cookie delayFeedbackUntil
to write the date until the popup should be delayed. Then, every time before rendering the popup, I have to make sure the current day is after the dealyFeedbackUntil
date.
Conclusion
It’s been a few days that the feedback widget is live on BrandBird and I’ve already got a few responses. For me, user feedback is a hidden power, and you always have to put effort into a seamless experience.
I’d love to learn your thoughts on my implements and your own ideas.