culture

Your Go-to Guide to Notification Customization with MagicBell

Allie Dyer Bluemel Last updated on September 26, 2024

In-app notifications can be, and often are, very distracting. They’re triggered by website logins, abandoned carts, and feature updates. But certain notifications, like when someone needs your attention on a design file, are important and time-sensitive. These notifications need a place to live that’s not intrusive to your workflow.

A notification inbox can be the answer to those management problems. Building a solution in-house is an option, but we want you to be able to focus on building the core features of your product, not spending time building an inbox for all those important notifications.

We make notification customization easy with our MagicBell React SDK, React-headless component, and Browser JS library. (with support for English, Spanish, and Brazilian Portuguese)!

Notification customization with the React SDK

Good design and simplicity can go a long way when dealing with notifications. Notification customization begins with choosing a type of inbox to store notifications on your site or in your app.

MagicBell is the root component in the SDK initializing a connection to magicbell.io. You can then implement the NotificationInbox or the FloatingNotificationInbox.

The NotificationInbox is an infinite scroll list with an accompanying header and footer. This would be ideal to use if you wanted to build a separate page or section of your application for users to access notifications.

The FloatingNotificationInbox is a tooltip render of the NotificationInbox. This would be ideal to use if you wanted to build users an easy way to access their notifications from any page.

For this demo, we’ll be looking at the FloatingNotificationInbox.

Example of FloatingNotificationInbox with the React SDK
//Updates.tsx

<MagicBell
   apiKey={MAGICBELL_API_KEY}
   userEmail="[email protected]"
   bellCounter="unread"
>
   {(props) => (
       <FloatingNotificationInbox
           height={450}
           NotificationItem={CustomNotification}
           layout={["content", "header"]}
           hideArrow
           {...props}
       />
   )}
</MagicBell>

This MagicBell component first takes the API key and the user email, then allows for customization. In this example, we are using the bellCounter to render the badge icon with the number of unread notifications. The icon, header, and footer are being assigned custom values inside the custom theme object.

The FloatingNotificationInbox is a tooltip component that renders notifications through the props. You can set the height and order the content within the component. In this example inside the layout, the content is referencing the notifications, and the header has been positioned below the notifications (as seen in the photo above).

The NotificationItem is rendering a CustomNotification component, which is customizing the props.

//CustomNotification.tsx

function CustomNotification({
 notification
}: CustomNotificationProps) {
 useNotificationWorkflow(notification);

 const handleClick = () => {
   if (!notification.isRead) notification.markAsRead();
   else notification.markAsUnread();
 };

 return (
   <div
     className={`custom-notification ${notification.isSeen ? "seen" : "unseen"}`}
   >
     <UnreadState notification={notification} />
     <div className="container" onClick={handleClick}>
     	<Sender notification={notification} />
       <div>
       	 <Title notification={notification} />
         <Timestamp notification={notification} />
         <Content notification={notification} />
         <Actions notification={notification} />
       </div>
     </div>
   </div>
 );
}

A notification can have three notification customization states:

  • unread
  • unseen
  • onAllRead

In this example, the UnreadState component is simply checking if the notification has been read, and if it has not been read, it renders a little blue SVG circle (as seen in the image above).

//UnreadState.tsx

function UnreadState({ notification }: { notification: Notification }) {
 return (
   <div className="unread-state">
     {notification.isRead ? null : (
       <svg viewBox="0 0 512 512">
         <circle cx="256" cy="256" r="64" />
       </svg>
     )}
   </div>
 );
}

The other components being rendered in CustomNotification are:

  • <Title notification={notification} />
  • <Timestamp notification={notification} />
  • <Content notification={notification} />
  • <Actions notification={notification} />

These render the notification data from MagicBell and display it in the tooltip.

You can play around with the React SDK demo here.

Notification customization with the React-headless component

If you want more control with the advantage of hooks already built, you can get started with the React-headless component, which fetches and shows MagicBell notifications. Since this is a headless component, you can wrap your entire app in the MagicBellProvider. In this example, we’ve built a quick solution for React Native.

Custom React Native solution with the React-headless component

The MagicBellProvider initializes a MagicBellContext, which keeps notifications updated in real time. There are three hooks to help you out.

First, useBell is a hook that gets the number of unseen or unread notifications from the current user's last visit.

function Bell({ color }) {
 const { badgeCounter } = useBell({counter: "unread"});
}

Second, useMagicBellEvent is a hook for real-time events:

useMagicBellEvent('notifications.new', (notification) => 
    {// Do something like showing a push notification});

You can use this hook to listen to:

  • notifications.new
  • notifications.read
  • notifications.read.all
  • notifications.unread
  • notifications.seen.all
  • notifications.delete

Third, useNotifications is a hook for getting notifications from the current authenticated user:

//NotificationInbox.js

import { FlatList } from "react-native";

function NotificationInbox() {
 const store = useNotifications();

 if (!store) return null;
 return (
 	<FlatList
 	 data={store.items}
 	 keyExtractor={(notification) => notification.id}
 	 renderItem={({ item }) => <Notification notification={item} />}
 	/>
 );
}

The headless component has support for multiple notification stores. This means it’s possible to have separate stores for unread and read by defining each one with a separate id and context.

<MagicBellProvider
    apiKey={MAGICBELL_API_KEY}
    userEmail="[email protected]"
    stores=[
    {id: 'read', context: { read: true }}, 
    { id: 'unread', context: { read: false }}]
>
    <App />
</MagicBellProvider>

The NotificationStore is a class that implements an interface with attributes, read-only properties, and methods. All the attributes are MobX observables. You can import the class from @magicbell/react-headless, but if you’d like to avoid creating a new instance in your app, you can also load it through MagicBellContext.

You can play around with the React-headless demo here.

Notification customization in the browser

If you need a quick implementation in the browser with vanilla JavaScript, we’ve got you covered with the MagicBell Browser JS library. Before your closing body tag, you can paste the following code snippet in (remembering to update the email and API key):

<div id="notifications-inbox" />
<script type="text/javascript">
  (function(i,s,o,g,r,a,m) {i['MagicBellObject'] = r;(i[r] =i[r] ||function() {
  (i[r].q = i[r].q || []).push(arguments);}),(i[r].l = 1 * new Date());(a = s.createElement(o)), (
  m = s.getElementsByTagName(o)[0]);a.async = 1;a.src = g;m.parentNode.insertBefore(a, m);
  })(window,document,'script','https://assets.magicbell.io/magicbell.min.js','magicbell');

  var targetEl = document.getElementById('notifications-inbox');
  var options = {
    apiKey: MAGICBELL_API_KEY,
    userEmail: CURRENT_USER_EMAIL,
    height: 500,
  };

  magicbell('render', targetEl, options);
</script>

With this solution in place, you can identify users with either their email via userEmail or by including the external_id parameter with the notification in the API and calling userExternalId in the front end.

A default theme is provided, meaning this solution can have you up and running with a working notification inbox quickly. If you want more notification customization and need to tailor the inbox to be on brand, you have that option with this solution as well.

You can customize the theme in the following ways:

  • Bell icon: color and size
  • Badge icon for unseen messages: color, font, and border radius
  • Header and footer: colors, font, and border radius
  • Three notification states (unseen, unread, or read): each state can have its own color and font settings
  • Empty inbox: the default image can be changed
Custom dark theme example

The stylesheets key allows you to use custom fonts:

theme: {
    header: { fontFamily: 'IBM Plex Sans' }
    notification: {
        default: { fontFamily: 'IBM Plex Sans' },
        unseen: { fontFamily: 'IBM Plex Sans' },
        unread: { fontFamily: 'IBM Plex Sans' },
    },
},
stylesheets: [
    'https://fonts.gstatic.com',
    'https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@200;500',
],

There’s also the ability to add your own custom hook when new notifications arrive. This would give you the ability to notify users in a custom way that they’ve received a new notification, like showing a toast or playing a sound.

Get up and running with a notification inbox

In addition to our demos on CodeSandbox, we have example stories of our components in Storybook. Check out the code behind the components to get a better idea of what kind of notification customization is possible.

If your application or website can benefit from a notification inbox, get started with MagicBell by requesting an API key (no waiting), and start playing around!