Back to search

Build realtime notifications for HTML5 apps using Ruby

  • Pusher team
July 18th, 2017
A basic understanding of Ruby and JavaScript is needed to follow this tutorial.

Why use HTML5 notifications?

There are few apps nowadays for which realtime notifications are not a core feature. From friend requests to pull requests, keeping users updated is key to their experience. Users want to be in the know about the content that interests them, and receive current information without the need for a browser refresh. It improves peer interactions between friends and colleagues, increases social reach, and triggers important conversations that could be invaluable to your app experience.

What we'll cover

  • A user will perform an action that will create a notification, and send it to the server.
  • When the server receives the notification data, it will broadcast it to other users using the server language's Pusher HTTP library.
  • All users running the web app will receive the notification via the Javascript Pusher WebSockets library. It will be shown in the application views.
  • We will use a third party library to enhance the notification experience.

Pusher terminology

The realtime web is sometimes referred to as “the evented web”. This is because our applications are full of events; events when data changes within your apps, events when users interact with an application and events when systems interact with each other.

Events take place on something: on a table in a database as a new record is created, updated or deleted; on a particular part of the user interface. Anything that results in a change in the underlying application state.

For this reason Pusher uses the terms channel for identifying and partitioning data and events for indicating actions upon that data.


In Pusher, channels are a way to organize your data. In this tutorial, we will use a channel called notifications, but for other things you might wish to add, such as chat-messages or user-activity, you will want to use new channels to appropriately categorize the data you send. To transmit notifications, we will be using public channels. Information on public channels is potentially accessible to anybody. To control access to information on channels you would use private channels.


Events are triggered on channels resulting in the event being distributed to all clients that are subscribed to that channel. They have a name, such as new_notification, and a JSON data payload, such as {message: 'hello world'}.

The tutorial

Now that you've grasped channels and events, let's get started with creating your own realtime notifications app!

Step 0: Setting up your FREE account

Sign up for a free account.

Make sure you have a server capable of running Ruby, PHP, Python or Node. With Ruby, we will be running Sinatra; Python with Flask; and Node with Express.

Install the Pusher library for your given language

  gem install pusher

Create an application, and name it whatever you wish, e.g. 'Notifications Tutorial'. On the page for your application, you’ll find your application credentials.

Create a directory called notifications with a structure that looks like this:

├── app.rb
└── views
    └── index.erb

If at any point you are stuck, feel free to browse the source code (the different languages can be found in different branches).

Step 1: Triggering an event

To start with, we'll just trigger an event on a channel, and view it in the Pusher debug console.

First off, import the Pusher package or library. And then we initialise our Pusher instance with our app credentials: our app_id, app_key, and app_secret.

Now, for testing purposes we’ll trigger an event called my-event on a channel called my-channel. We'll give this event an arbitrary payload, such as {message: 'hello world'}.

require 'pusher'

pusher = app_id: 'YOUR APP ID', key: 'YOUR APP KEY', secret: 'YOUR APP SECRET'

# trigger on 'my-channel' an event called 'my-event' with this payload:

pusher.trigger('my-channel', 'my-event', {
    message: 'hello world'

You should see the event pop up in the Pusher debug console. Pretty nifty, huh?


Step 2: Creating a very basic app

On your client

Let's jump in and see what we do on the client-side when using Pusher.

Include the Pusher JavaScript library in your index.html file. We’ll also include jQuery for rendering notifications in the UI:

<script src="//"></script>
<script src="//"></script>

To get things started, let's initialize our Pusher instance in a HTML script tag:

    var pusher = new Pusher('YOUR_APP_KEY');

Essentially, we wish to bind to an event on a channel, and pass a callback to be called any time the event takes place, such as this:

myChannel.bind('my-event', function(data){
    // do something with our `data`

Let's bind to an event called new_notification on the notifications channel and show it in a <div>:

//subscribe to our notifications channel
var notificationsChannel = pusher.subscribe('notifications');

//do something with our new information
notificationsChannel.bind('new_notification', function(notification){
    // assign the notification's message to a <div></div>
    var message = notification.message;

Now, within your HTML, create a div, with class 'notification', such as <div class="notification"></div>. Your HTML should look like this:

    <title>Realtime Notifications</title>
    <script src="//" type="text/javascript"></script>
    <script src="//" type="text/javascript"></script>

    <div class="notification"></div>


        var pusher = new Pusher('YOUR_APP_KEY');

        var notificationsChannel = pusher.subscribe('notifications');

        notificationsChannel.bind('new_notification', function(notification){
            var message = notification.message;



On your server

We’ll slightly modify our existing code so that whenever somebody makes a GET request to the /notification endpoint, this code will be executed and a new_notification event will be triggered on the notifications channel.

require 'sinatra' # requires `gem install sinatra`

get '/notification' do
    pusher.trigger('notifications', 'new_notification', {
        message: 'hello world'
    "Notification triggered!"

# don't forget to render your index.html page

get '/' do
    erb :index
{::code lang="python" id="endpoint"}
from flask import Flask # requires `pip install flask`
from flask import render_template
from flask import request
app = Flask(__name__)

def show_index():
    return render_template('index.html')

def trigger_notification():
    p.trigger('notifications', 'new_notification', {'message': 'hello world'})
    return "Notification triggered!"

if __name__ == "__main__":
router.get('/', function(req, res){

    pusher.trigger('notifications', 'new_notification', {
        message: "hello world"

    res.send("Notification triggered!")

Run your server and open '/', showing index.html, on one browser window.

Then, open the /notification URL in another browser window and you will see 'hello world' appear on the first window.

Step 3: Make it interactive

On your client


That's all well and good - but what if we want to create notifications that say something other than 'hello world'? Let's make it so that we create a notification to all users whenever we submit some text to the UI.

Let's create our input:

<input class="create-notification" placeholder="Send a notification :)"></input>
<button class="submit-notification">Go!</button>

Now, whenever clicks 'Go!', we want to POST to our /notification endpoint with the message to broadcast.

var sendNotification = function(){

    // get the contents of the input
    var text = $('input.create-notification').val();

    // POST to our server
    $.post('/notification', {message: text}).success(function(){
        console.log('Notification sent!');

$('button.submit-notification').on('click', sendNotification);

On your server

Server-side, we'll just want to replace our hard-coded 'hello world' message with whatever was posted to that endpoint. Furthermore, we'll want to make sure our code handles a POST request. This is so that we can POST messages to this endpoint to the client to create a notification.

post '/notification' do
    message = params[:message]

    pusher.trigger('notifications', 'new_notification', {
        message: message

Now, open up a second browser to show the index.html file. If you type a piece of text into your input box and click ‘Go!’, you'll see that all browsers receive your new notification.

Step 4: Improve the notification experience

Toastr is a fairly popular and easy-to-use library for nice, non-blocking in-app notifications. In showing you how to further extend your notifications app, let's use it to display new notifications in the UI.

Link in the Toastr CSS and Javascript in your between your <head> tags in index.html:

<link rel="stylesheet" href="//">
<script src="//"></script>

Remove our <div class="notification"></div> as we won't need it any more.

At the time of writing, toastr does not have HTML escaping built in. So at this point, to encourage security and best practices, we should escape our HTML before rendering it to the DOM. Otherwise, our app would be vulnerable to HTML script injection attacks. This should be straightforward; at our notification where we receive new notification POSTs from the client, let's sanitize the message.

require 'cgi'

post '/notification' do
    message = CGI.escape_html params[:message]

    pusher.trigger('notifications', 'new_notification', {
        message: message

Now, on the client, let's call toastr.success in our new_notification Pusher callback.

notificationsChannel.bind('new_notification', function(notification){
    var message = notification.message;

So, test it out! You can open up a new browser window to check it works.

What Now?

Try out our (only slightly) prettier demo in multiple browser windows or in your browser and on your phone / tablet.

Have a look at our documentation to other ways in your can integrate Pusher into your application.

To extend what you've built, you might want to have a look at the other types of notification Toastr can provide.

Alternatively, you could exclude the sender of the notification from receiving the alert, by using socket_ids to filter recipients.

Here are links to other Javascript notification libraries you can use:

  • Channels

© 2018 Pusher Ltd. All rights reserved.

Pusher Limited is a company registered in England and Wales (No. 07489873) whose registered office is at 28 Scrutton Street, London EC2A 4RP.