Simple Web Push Notifications with SendPulse and Laravel
Update: Firefox now supported
We are all familiar with mobile app notifications and thanks to web push notifications it is now becoming increasingly possible to recreate this experience without an installed app.
Web push notifications allow users to subscribe to site notifications by responding to a single prompt and enable you to reach your web users even once they have left your site. Whilst web push notifications work with desktop browsers (currently Chrome, Safari running Mavericks or later and Firefox very soon) they shine for Android users where they truly offer a native app experience as the following sample web push message demonstrates.
This isn’t quite the holy grail it first appears as iOS isn’t supported and implementation varies by browser and OS, notably desktop notifications on OSX.
There are plenty of resources for learning more about web push notifications and Google offers an excellent tutorial if you wish to tackle the problem on your own. Apple’s Safari Push notification documentation is located here. Fortunately however there are a growing number of services that manage the process of managing subscribers and message delivery and so you do not have to concern yourself with the multiple implementations.
It is a rapidly expanding market with established services such as Roost being joined by the likes of OneSignal, PushCrew and XtremePush among others. After testing many different solutions I ended up using the SendPulse service primarily due to their excellent free tier, clear pricing and a well documented API with several client libraries.
Installation is as simple as inserting a single line of JS into your page and including a couple of files (a service worker and manifest file, which perform the behind-the-scenes magic for Chrome). For native notifications you will need your site to be served over HTTPS as service workers enable potential man-in-the-middle attacks. Fortunately GitHub pages offer SSL support and so can be used to test the service.
For the following example I installed a sample Twitter Bootstrap site with the required files from SendPulse to https://garethtdavies.github.io/. The page will prompt users to accept notifications from the site and will send an immediate test message when accepted. On Chrome on an Android device the notification looks like like this:
You should also take note of a powerful feature in the docs that you may customise the installation for each user by sending custom variables that you may later use to target message delivery.
And that is it for the SendPulse setup and you can start using their website control panel or API to send messages to subscribed users! For the remainder of this article we will install a package to simplify using the service directly from within a Laravel application.
The SendPulse API is well documented and they provide a PHP client library which will handle, among other things, the API authentication for you. Unfortunately this package isn’t currently composer installable so for the purposes of this article I created a composer-ready version as well as a Laravel service provider which provides a SendPulse facade as well as an instantiated SendPulse client ready for delivering notifications. After installation sending a notification from within a Laravel application is as simple as:
$data = [
'title' => 'Test push title',
'website_id' => 1,
'body' => 'Test push message',
'ttl' => 300, //push notification lifetime
'stretch_time' => 0, //how long to spread message delivery
'link' => 'https://github.com/garethtdavies'
Using the default settings a token will be stored in your public directory but you may change this to store the token in either a session variable or via memcache.
Other methods of the SendPulse web push API enable quick retrieval of websites and variables, statistics and setting a user’s subscription state. A full listing of all available methods is available below:
SendPulse::pushListCampaigns($limit = null, $offset = null);
SendPulse::pushListWebsites($limit = null, $offset = null);
SendPulse::pushListWebsiteSubscriptions($websiteId, $limit = null, $offset = null);
For many methods you will need the website_id which may be obtained through either the SendPulse control panel or by using the SendPulse::pushListWebsites() method. Whilst for many options there are sensible defaults, notably the stretch_time parameter (time for which a push campaign is throttled) defaults to 5 hours, which if not set to a lower value may cause some frustrations during testing! If all works well here’s the final notification delivered: