You don't need to build an admin panel for your SaaS!

You don't need to build an admin panel for your SaaS!

When you launch your product, having an admin panel is the least of your priorities.

Building features for your users is far more important and fun than building something only you would use, right?

After all, you can always access the database directly and tweak the records when needed.

This used to be my admin panel for the past 10+ years

But as the years go by, the user base grows, ticket requests flow, and you find yourself spending your productive days handling customer queries even though you have a support team. You can't give them database access or expect them to know SQL or Mongo.

And if you encrypt a user's Personal Identifiable Information (PII), which you must, databases become obsolete.

I knew having an admin panel was overdue, but I still didn't feel like building one.



Solution: Pick a CRM or unified inbox that has an API

Since 2020, we have been using Crisp as our centralized support hub for Publer: Live chat, emails, and social messages in one place.

Disclaimer: this is not a sponsored article

So, even if I decided to build an admin panel, which is more of building another SaaS, the support team would still have to navigate multiple dashboards to map the user data.

That's far from efficient. Ideally, you would want to have everything in one place.

After months of research, development, and integrations, here's how I delegated all customer-related actions to my team right within Crisp!



1. Sync your user data with Crisp

Consider Crisp an external duplicate database of your SaaS users, meaning you must update Crisp every time something changes.

Setting up Crisp is very easy, so I will skip this part

I added a new field to my user model in Ruby as the foreign key between the two databases.

field :crisp_id, type: String, default: nil        

Then, I wrote a Sidekiq worker to call the Crisp API in the background every time the user, or any other models related to the user, are updated.

after_save do
  Crisp::AddOrUpdateContactWorker.perform_async(id, crisp_id)
end        

The worker will either create a new contact in Crisp for new registered users or update the contacts for the existing users.

module Crisp
  class AddOrUpdateContactWorker
    include Sidekiq::Worker

    def perform(user_id, crisp_id)
      @user = User.find(user_id)
      @crisp_id = crisp_id
      @website_id = ENV['CRISP_WEBSITE']

      if @crisp_id
        update_contact
      else
        add_contact
      end
    end
  end
end        

In Crisp, we store the main profile info such as email, name, avatar, and timezone.

person = { nickname: @user.name.presence || @user.email.split('@').first }
person[:avatar] = @user.picture if @user.picture.present?
person[:timezone] = @user.settings.timezone

user_profile = { email: @user.email, person: person }

$crisp.website.add_new_people_profile(website_id, user_profile)

# or

$crisp.website.update_people_profile(website_id, crisp_id, user_profile)        

Most importantly, we store custom data crucial to both the support and marketing teams, such as the plan the user is on, how many social accounts they have, etc.

Because of the continuous syncing, all information our app sends to Crisp for a customer is available in real-time in the Crisp dashboard for our support team.

Once a user deletes their Publer account, this worker automatically removes it from Crisp.

before_destroy do
    Crisp::RemovePeopleProfileWorker.perform_async(id, crisp_id)
end        

As with most CRMs, Crisp charges per # of contacts, so why pay for deleted users?



2. Build widgets for customer actions

Reading and syncing the customer data was the easy part. The most challenging one was allowing my team to perform actions on a customer, such as issuing refunds, extending subscriptions, offering discounts, or even updating a customer's email.

A great thing about Crisp is its marketplace and the ability to build private actions through widgets, aka iframes.

This means I had to develop the interface and logic for each action and then have Crisp widgets load them as iframes. Example of an iframe URL:

https://app.publer.io/admin/invoices?user_id={conversation.contact_data.id}&operator_name={operator.first_name}&operator_email={operator.email}&operator_avatar={operator.avatar}        

The parameters help our backend load the info for the correct user and log the operator details for transparency and accountability.

This public URL is safe to share because you also need a token that Crisp automatically passes when it loads the iframe

Here's an example of a basic HTML view I built for listing and refunding invoices.

The support team can access and use all these custom actions within Crisp without jumping through hoops.

Pro-tip: Have the backend send an automated message to the customer after an action is performed

I don't think programmers are the only ones who hate repeated actions.

This way, the support team won't have to type the same messages, such as "I just issued you a refund" or "I just created this coupon" over and over again repeatedly.



3. Bonus: Use Crisp for email marketing

Crisp is not a marketing platform per se. However, after rigorous research and not feeling like integrating and paying for another platform, I made Crisp campaigns work for our needs.

You can use a custom email template for campaigns, so I simply copied the HTML template we internally use for transactional emails, i.e. verifying your email address.

Although the rich editor is a bit basic, it allows you to compose and preview your email campaigns quickly.

Having dynamic variables from the custom data is a big plus for personalization.


One-shot Campaigns

We manually send these marketing emails, such as product updates or announcements, for which our users can opt-in.

The custom data stored in Crisp and continuous syncing help us target only the recipients who expect our email.

My only problem with Crisp is that emails are not sent based on the user's time zone. Which means that someone may get the email at 4 AM.



Automated Campaigns

Believe it or not, I had not touched the welcome email in 6 years because it was part of our hard-coded transactional emails and, thus, not user-friendly to modify.

These automatic emails are now sent to users through Crisp after they take action, in this case, joining our platform.

This can be enabled on Crisp by selecting the event from a pre-defined list.

The events can be defined or sent to Crisp using their API. Example:

Crisp::AddPeopleEventWorker.perform_async(user.id, event)        

The above background worker is called for all kinds of events we care about, such as upgrades or cancellations.

We recently started sending emails with tips through Crisp to improve our onboarding process.

For example, you will automatically receive an email on how to use Publer to grow your LinkedIn account AS SOON AS you connect your LinkedIn account.

The best part is that the content of these emails can be easily modified at any time. We can add and remove new use cases on the go.

We can also track the performance, even though analytics is not Crisp's strongest aspect.




Thank you for reading!

The Crisp ecosystem has helped me save a lot of headaches and hours of work every day.

The best part is that even if we decide to switch CRMs in the future, the infrastructure I have built on our end can be easily ported over.

If you enjoyed this article, follow me at Ervin Kalemi and subscribe to my newsletter.




Topics I plan to cover next:

  • Building an affiliate program from scratch
  • Going through the CASA security assessment
  • The importance of registering your trademark
  • How I bootstrapped Publer to $2M+ in ARR


Iris Zanaj

Software Developer at Vodafone Ziggo Netherlands

9 个月

Interesante, kur thua ske nevoje per admin panel por ke Crisp, tek manaxhon dhe subscription e klientve?

回复
Marsel Kalemi

Leading our team toward personal & professional success | Founder & CEO at Kalemi Travel, Kalemi B2B Booking System

9 个月

Interesante! Une s'e dija qe mund te beheshin keto, jo me te di si t'i bej teknikisht ?? Te intereson nje part time job si konsulent? ??

Erion O.

Software Engineer, MBA

9 个月

Shume bukur! Morem disa ide te reja

Baf Kurtulaj, MBA

Co-founder & CEO at Presto | Building the Digital Backbone of the Future Dental Ecosystem | Raising SEIS/EIS.

9 个月

Great article. As it happens I am evaluating few CRMs for something we are working on and Crisp IM seems to be flexible and customisable

要查看或添加评论,请登录

Ervin Kalemi的更多文章

  • Publer 2024 Year In Review

    Publer 2024 Year In Review

    New office. New domain.

    1 条评论
  • Acquiring the publer.com domain after 12 years!

    Acquiring the publer.com domain after 12 years!

    The publer.com domain must have cost me a fortune, right? To put things into perspective, I acquired the kibo.

    25 条评论
  • 2023 Year In Review

    2023 Year In Review

    AI, Twitter API, Threads App … what a crazy year this has been for Publer and the social media universe! Let’s take a…

    13 条评论
  • How To Post Carousels On LinkedIn

    How To Post Carousels On LinkedIn

    What are LinkedIn carousel posts? Even though LinkedIn does not officially refer to them as carousels, you have…

    10 条评论
  • How to Migrate a Subdomain or a Domain to a Subdirectory on a Different Server

    How to Migrate a Subdomain or a Domain to a Subdirectory on a Different Server

    When we rebranded Publer, we decided to split the website, the platform, and the blog from one another as they're built…

    11 条评论
  • Why Marketing Agencies Must Utilize a Social Media Management Platform

    Why Marketing Agencies Must Utilize a Social Media Management Platform

    We are not an agency, nor have we collaborated with one for our social media presence; however, I have gained…

    1 条评论
  • Publer 2022 Year In Review

    Publer 2022 Year In Review

    In a blink of an eye, another year has passed, so it’s time to pause, look back, and reflect. As promised in my last…

    6 条评论
  • How we failed the Product Hunt launch

    How we failed the Product Hunt launch

    Last month, we finally launched Publer on Product Hunt. Even though we managed to rank as the #4 product of the day and…

    4 条评论
  • How we made $250,000 on AppSumo

    How we made $250,000 on AppSumo

    As we're getting ready to introduce Publer to the Product Hunt community, I would like to go down memory lane and share…

    27 条评论
  • The aftermath of rebranding Publer and doubling our prices

    The aftermath of rebranding Publer and doubling our prices

    If there’s one thing that Publer was missing and kept our plans underpriced, was the branding. Some background story…

    13 条评论

社区洞察

其他会员也浏览了