One Signal Notifications on Gatsby

Posted on April 04, 2019

Notifications are now an integral part of the web ecosystem. It increases the user engagement rate and your site can organically have people coming back day after day with fresh content.

Gatsby is the most popular Blog React Framework in town and that is what we will be pairing up with popular free (mostly) notification service One Signal.

We will be looking at Web Push in this article.

1. Login with OneSignal

Create an Account on OneSignal, it’s pretty much free to start with.

2. Add a new App on OneSignal Dashboard

You can add any (identifiable) name you want and select No Organisation under the organisation dropdown. Add the app and select Web Push as the required platform. (Onesignal has docs for almost every platform out there, web push is just the one we will cover).

3. Setup Page

Setup Page
Setup Page

The Typical Site option is the easiest and but it is not going to have the UX we want, click on the Custom Site option.

Follow the instructions in official docs to complete the form.

4. Site setup

You will now get to download three files.

These are manifest.json file, OneSignalSDKWorker.js and OneSignalSDKUpdaterWorker.js. What we have to achieve now is to upload these to the top level directory.

If you are using gatsby, you probably have gatsby-plugin-manifest somewhere in your configuration. If you do, just copy the gcm_sender_id from the manifest you downloaded and add it to manifest config.

Sample

Copy the other two files into the static folder of gatsby. All files inside this folder will be copied over to the build folder and hence satisfies the top level directory requirement.

The next step is to include OneSignal SDK URL into HTML head. It is specifically said that it should be from a CDN and not loaded from the local. But we do not normally edit head inside Gatsby applications.

We have instructions for editing the head of HTML doc here: Customizing html.js

You can copy HTML with:

1cp .cache/default-html.js src/html.js

In the new HTML file, add:

1<script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async="" />

to the head.

Adding a react component with link.

1import React, { PureComponent } from 'react';
2import * as S from './layout';
3class NotificationsForm extends PureComponent {
4 constructor(props) {
5 super(props);
6 this.state = {
7 permission: 'default',
8 };
9 }
10 componentDidMount() {
11 this.OneSignal = window.OneSignal || [];
12 this.setupOneSignal();
13 }
14 /**
15 * Render subscribe button
16 * @param {('default'|'denied'|'granted')} permission - permission level
17 * @returns {import('react').ReactElement} React Node
18 */
19 renderBtn = permission => {
20 if (permission === 'default') {
21 return (
22 <S.SubmitBtn as="button" onClick={this.onSubscriptionBtnClick}>
23 Subscribe
24 </S.SubmitBtn>
25 );
26 } else if (permission === 'granted') {
27 return (
28 <h5>
29 Already part of Notification Squad{' '}
30 <span role="img" aria-label="relieved face">
31 🎉
32 </span>
33 </h5>
34 );
35 } else if (permission === 'denied') {
36 return (
37 <h5>
38 Thank You for your time.{' '}
39 <span role="img" aria-label="relieved face">
40 😌
41 </span>
42 </h5>
43 );
44 } else {
45 console.warn('Unrecognised permission', permission);
46 }
47 };
48 render() {
49 const { permission } = this.state;
50 return (
51 <div>
52 <S.SubSection>
53 <S.Subtitle>Notifications</S.Subtitle>
54 <sub>As it Happens.</sub>
55 </S.SubSection>
56 {this.renderBtn(permission)}
57 </div>
58 );
59 }
60 onSubscriptionBtnClick = event => {
61 this.getSubscriptionState().then(state => {
62 if (state.isPushEnabled) {
63 /* Subscribed, opt them out */
64 this.OneSignal.setSubscription(false);
65 } else {
66 if (state.isOptedOut) {
67 /* Opted out, opt them back in */
68 this.OneSignal.setSubscription(true);
69 } else {
70 /* Unsubscribed, subscribe them */
71 this.OneSignal.registerForPushNotifications();
72 }
73 }
74 });
75 event.preventDefault();
76 };
77 setupOneSignal = () => {
78 this.OneSignal.push(() => {
79 if (!this.OneSignal.isPushNotificationsSupported()) {
80 return;
81 }
82 this.OneSignal.init({
83 appId: '1a5a3a21-f5d1-4a88-a3ab-f8219fbbacea',
84 autoResubscribe: true,
85 notifyButton: {
86 enable: false,
87 },
88 });
89 this.updateManageWebPushSubscriptionButton();
90 this.OneSignal.on('subscriptionChange', function() {
91 this.updateMangeWebPushSubscriptionButton();
92 });
93 });
94 };
95 updateManageWebPushSubscriptionButton = async () => {
96 try {
97 const state = await this.OneSignal.getNotificationPermission();
98 this.setState({
99 permission: state,
100 });
101 } catch (error) {
102 console.error('Error getting notification status', error);
103 }
104 };
105 /**
106 * Find current subscription state
107 **/
108 async getSubscriptionState() {
109 const result = await Promise.all([
110 this.OneSignal.isPushNotificationsEnabled(),
111 this.OneSignal.isOptedOut(),
112 ]);
113 const [isPushEnabled, isOptedOut] = result;
114 return {
115 isPushEnabled: isPushEnabled,
116 isOptedOut: isOptedOut,
117 };
118 }
119}
120default NotificationsForm;

Find the file here

Feel free to create an issue if you need help.