Nowadays, users are more likely to receive communication from multiple channels.
The fundamental reason for this is that consumers expect to be able to tailor communication channels to their own requirements—which compels developers to handle all of those APIs across the codebase. Notifications come in a variety of shapes and sizes; from Reddit to Facebook, Twitter, and beyond.
To customers, the notifications represent updates on their favorite people, businesses, and interests. A notification system, therefore, is a strong approach for web developers and SaaS marketers to get their goods in front of the people who matter.
There is a wealth of knowledge available, but people only have so much time and capacity to share, meaning only the most attractive services will be able to properly woo their target demographic.
Simultaneously, the popularity of native notification systems across online browsers and mobile operating systems is beneficial to organizations who can utilize them successfully for customer outreach. These timely messages can have a huge impact on client retention and engagement performance.
In this article, you will learn about Notifire, how it’s implemented, and its versatility in offering opportunities to target end users according to specific needs.
Notifire is a powerful and customizable open source notification infrastructure that uses a single API to manage multi-channel transactional notifications.
Benefits and features of Notifire:
Notifire is written in TypeScript; you can create a notification layer in just a few minutes with Notifire.
Before diving into the implementation, you need to understand the architecture behind the library in order to gain clarity on how notifications are supercharged with Notifire.
Notifire’s architecture focuses on the separation of concerns. According to this principle, transactional communication is made up of many independent elements, each of which is accountable for a certain job. In order for extra functionality to be readily incorporated and maintained, the communication layer must be modeled.
Have a look at the diagram below.
The following elements ensure the successful flow of delivering notifications to your end users:
Templates act as a blueprint and provide a skeleton or structure for each message. Each message is linked with a specific channel, for which a content template and coding rules—like filters, priority, and other metadata affecting the delivery of a given message—are supplied.
Providers are responsible for message delivery. They are in charge of providing alerts to end users via the designated channel. Notifire handles state and mediates all provider-specific customizations, since each provider is stateless and conforms to a specified interface.
The variables and data necessary to display the notification messages will be sent by each trigger. If a value is not present, the variable protection mode is activated and the message is not transmitted.
Triggers are responsible for informing the system that an event occurred, but not where and when the message will be delivered.
The communication engine is responsible for reading the template configurations, determining the necessary channels, connecting with the providers, and performing delivery of the alerts. Timing, priority, and channel are all maintained by the communication engine.
During runtime execution, these two layers manage the configuration and are saved in memory for further use. Each of the stores offer interfaces to query the providers and templates to be used by the communication engine.
Let’s have a look at the template-based approach in Notifire.
Templates hold the necessary metadata for message delivery. These templates can be re-used and stored in the Template Store for access. It contains major sections such as subject
, channel
, template
, and active
switches.
Have a look at the simple example below:
const UpdateEmailTemplate = await notifire.registerTemplate({ id: "update-email", messages: [ { subject: "Your email update request", channel: ChannelTypeEnum.EMAIL, // Email Channel template: ` Hi {{firstName}}! To update your email, click <a href="{{emailLink}}">here.</a> {{#if organization}} <img src="{{organization.logo}}" /> {{/if}} `, }, { channel: ChannelTypeEnum.SMS, // SMS Channel template: ` Hey {{firstName}}, here's the link to update your email: {{emailLink}} `, active: (trigger) => !trigger.$phone, }, ], });
As you can see, the messages
array holds a list of communication channels and corresponding message details to be sent to the users. You can personalize the channel experience by including channel-specific details similar to the above example.
channel
specifies the medium through which the user needs to be informed. Based on the channel
selected, an appropriate provider is used from the Provider Store.
The examples of channels can be: SMS
, EMAIL
, PUSH
, DIRECT_MESSAGE
, IN_APP
. Each channel
specified with its enum value holds its object block as shown in the above example.
The template
variable holds the message content. Notifire makes use of Handlebars so you can write your templates in the Handlebars expression format, as demonstrated in the following example:
{{#each tasks}} {{title}} {{#if done}} <span> Done </span> {{/if}} {{/each}}
The active
switch is used to determine whether the message should be sent or not on the basis of boolean value provided. active
is also used to send messages based on Triggers.
Notifire provides a plug-and-play solution for providers which typically stays on standby mode once loaded in the Provider Store’s memory. Let’s have a look at the list of providers supported by Notifire:
Emails are one of the most common and widely used channels of communication. Notifire provides the below interface to implement your own version of channel
:
export interface IProvider { id: string; // ID of the template channelType: ChannelTypeEnum; // Type of channel such as EMAIL } export interface IEmailOptions { to: string | string[]; // One or multiple recepients subject: string; // Subject of the email html: string; // Content body of the email from?: string; // Email ID of the sender text?: string; // Plain text content body of the email } export interface IEmailProvider extends IProvider { channelType: ChannelTypeEnum.EMAIL; sendMessage(options: IEmailOptions): Promise<any>; // Method to be overridden to send email message }
Popular email providers—including SendGrid, Mailgun, AWS SES, Postmark, NodeMailer, Mailjet, Mandrill, SendinBlue, EmailJS—are currently supported and the number of supported providers is constantly growing.
To register a specific email provider, you need to register it with the Notifire library as shown below:
import { SESEmailProvider } from "@notifire/ses" // Import your required provider const provider = new SESEmailProvider({ // Declare your provider region: "eu-west-1", //// accessKeyId: "AWS_ACCESS_KEY_ID", //// Provide configuration details to register your provider secretAccessKey: "AWS_SECRET_ACCESS_KEY", //// from: "[email protected]", //// }); // import { MailgunEmailProvider } from '@notifire/mailgun'; // Mailgun email provider const provider = new MailgunEmailProvider({ apiKey: process.env.MAILGUN_API_KEY, domain: process.env.MAILGUN_DOMAIN, username: process.env.MAILGUN_USERNAME, }); import { SendinblueEmailProvider } from './sendinblue.provider'; // SendinBlue email provider const provider = new SendinblueEmailProvider({ apiKey: process.env.SENDINBLUE_API_KEY });
Just like email, Notifire allows SMS providers as well. Below is the interface used to implement the SMS provider:
export interface IProvider { id: string; // ID of the template channelType: ChannelTypeEnum; // Type of communication channel } export interface ISmsOptions { to: string; // Number on which SMS needs to be sent content: string; // Content body to be sent in the SMS from?: string; // Number of the sender } export interface ISmsProvider extends IProvider { sendMessage(options: ISmsOptions): Promise<any>; // Method to be overridden to send email message channelType: ChannelTypeEnum.SMS; }
Popular SMS providers including Twilio, AWS SNS, and Plivo are currently supported and the number of supported SMS providers is also growing. To register a specific SMS provider, you need to register it with the Notifire library as shown below:
import { TwilioSmsProvider } from '@notifire/twilio'; // Twilio SMS provider const provider = new TwilioSmsProvider({ accountSid: process.env.TWILIO_ACCOUNT_SID, authToken: process.env.TWILIO_AUTH_TOKEN, from: process.env.TWILIO_FROM_NUMBER, // a valid twilio phone number }); import { SNSSmsProvider } from "@notifire/sns" // AWS SNS provider const provider = new SNSSmsProvider({ region: "eu-west-1", accessKeyId: "AWS_ACCESS_KEY_ID", secretAccessKey: "AWS_SECRET_ACCESS_KEY", }); import { PlivoSmsProvider } from '@notifire/plivo'; // Plivo SMS provider const provider = new PlivoSmsProvider({ accountSid: process.env.PLIVO_ACCOUNT_ID, authToken: process.env.PLIVO_AUTH_TOKEN, from: process.env.PLIVO_FROM_NUMBER, });
As you can see, it is straightforward to plug-and-play your favorite provider as per your need; all you need to do is register the provider with Notifire using the configuration and start using the templates declared.
Apart from email and SMS providers, Notifire will expand in the future to allow for setting up providers for direct messages, push notifications, and in-app messages.
This will include providers ranging from Slack, Microsoft Teams, Discord, PagerDuty, AWS SNS, and many more.
Many organizations today use a variety of different communication platforms and things start to get messy as the list of such platforms continues to grow. Notifire has solved this issue quite intelligently by making use of components like templates in the architecture.
When scaling your product or service, your implementation needs to handle the scale of users and communication as well.
Below are a few best practices that you should follow to ensure a great experience for your users.
Using generic, lengthy, and impersonal material in a push message is a significant error that can overwhelm and upset the recipient. Such alerts may cause the mobile app linked with that particular push message to be uninstalled.
Sending notifications or communication without sufficient business intelligence (BI) and consumer behavior analysis might result in a poor user experience and you might end up targeting non-relevant users.
One of the most common mistakes marketers make when utilizing push notifications is delivering them at the wrong time. It is not a good idea to send messages during hectic work hours or late at night. This may irritate users, and as a result, they may stop using your product or services.
In many situations, marketers make this error by sending generic notifications without doing a sufficient behavioral analysis of behavioral traits, personal data, location information, and client interest.
There are several sorts of users that respond to alerts in various ways. A large majority of users, 57 percent, read and open the app to answer instantly if the message is suitably tailored.
When users have been thoroughly onboarded, you may send them a push notice welcoming them to the app. Alternatively, you may get them off to a good start by providing a discount coupon for a product you offer. Also, as a taster, provide them with some free goodies—anything to offer them a taste of your software and entice them to use it more.
Targeting users with appropriate notifications and communication is crucial in today’s digital marketplace.
It goes without saying that notifications have surpassed all other modes of communication between apps, products, services, and their users.
As a result, a modern organization’s presence requires a strong notification strategy.
Notifire provides a platform to build and scale your notification infrastructure with amazing capabilities.
As the use cases grow and expand, Notifire is set to provide a plethora of options and provider implementations for you to seamlessly incorporate in your workflow.
This solution aims to act as a hassle-free solution for developers with promising capabilities.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowAngular’s two-way data binding has evolved with signals, offering improved performance, simpler syntax, and better type inference.
Fix sticky positioning issues in CSS, from missing offsets to overflow conflicts in flex, grid, and container height constraints.
From basic syntax and advanced techniques to practical applications and error handling, here’s how to use node-cron.
The Angular tree view can be hard to get right, but once you understand it, it can be quite a powerful visual representation.