BananaNeil
BananaNeil

Reputation: 10762

Open a custom url when clicking on a web push notification

I am implementing the Webpush ruby gem to send push notifications to users of my website.

Server code:

  Webpush.payload_send({
      message: notification.message,
      url: notification.url,  # I can't figure out how to access this key
      id: notification.id,    # or this key from the service worker
      endpoint: endpoint,
      p256dh: p256dh_key,
      vapid: vapid_keys,
      ttl: 24 * 60 * 60,
      auth: auth_key,
    })

I have a service worker set up on the client side to show the notification and make it clickable.

self.addEventListener("push", function (event) {
  var title = (event.data && event.data.text()) || "New Message";

  event.waitUntil(
    self.registration.showNotification(title, {
      body: "New push notification",
      icon: "/images/[email protected]",
      tag:  "push-notification-tag",
      data: {
        url: event.data.url, // This is returning null
        id: event.data.id // And this is returning null
      }
    })
  )
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
    clients.openWindow(event.data.url + "?notification_id=" + event.data.id)
  );
})

It is all working fine, except the custom keys (url, id) that I am passing through are not accessible from within the service worker.

Does anyone know how to pass custom data through the WebPush gem?

Upvotes: 27

Views: 37477

Answers (4)

Puneet Pandey
Puneet Pandey

Reputation: 555

For Webpush Ruby Gem, with some modifications, here's what worked for me:

Webpush.payload_send(
  endpoint: user.push_subscription.endpoint,
  message: {
    message: "A new service request is created",
    id: service_request.request_number,
    url: "https://google.com/"
  }.to_json,
  p256dh: user.push_subscription.key,
  auth: user.push_subscription.auth_key,
  ttl: 24 * 60 * 60,
  vapid: {
    subject: 'A Push Notification',
    public_key: ENV['VAPID_PUBLIC_KEY'],
    private_key: ENV['VAPID_PRIVATE_KEY']
  }
)

Where:

  • user.push_subscription.endpoint is a method defined in PushSubscription model to return the endpoint
  • user.push_subscription.key, user.push_subscription.auth_key are again methods defined in the same model

Inside /serviceworker.js.erb

self.addEventListener("push", (event) => {
  let response = event.data && event.data.text();
  let title = JSON.parse(response).message;
  let body = JSON.parse(response).id;
  let icon = '/assets/logo-blue-120x120.jpg';

  event.waitUntil(
    self.registration.showNotification(title, { body, icon, data: { url: JSON.parse(response).url } })
  )
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
    clients.openWindow(event.notification.data.url)
  );
});

Upvotes: 3

cyperpunk
cyperpunk

Reputation: 702

Add this on your Angular project inside the node_modules/@angular/service-worker/ngsw-worker.js

this.scope.addEventListener('notificationclick', (event) => {
            console.log('[Service Worker] Notification click Received. event:%s', event);
            event.notification.close();
            if (clients.openWindow && event.notification.data.url) {
                event.waitUntil(clients.openWindow(event.notification.data.url));
            }
        });

You can enter the above code where you can find this line inside the file

this.scope.addEventListener('notificationclick', (event) => ..

And you have to build the dist again for this to work. And in backend you would need to use this format:

{"notification":{"body":"This is a message.","title":"PUSH MESSAGE","vibrate":[300,100,400,100,400,100,400],"icon":"https://upload.wikimedia.org/wikipedia/en/thumb/3/34/AlthepalHappyface.svg/256px-AlthepalHappyface.svg.png","tag":"push demo","requireInteraction":true,"renotify":true,"data":{"url":"https://maps.google.com"}}}

Inside the url you can enter your url and on clicking notification your push notification will open the given link and focus it in the browser

Upvotes: 0

munjal
munjal

Reputation: 1404

Custom data comes in event.notification object not in event directly(in notificationclick). So if you want to fetch the custom data variable in notificationclick function, then you should do it like this :)

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
    clients.openWindow(event.notification.data.url + "?notification_id=" + event.notification.data.id)
  );
})

Upvotes: 22

Jonas Wilms
Jonas Wilms

Reputation: 138267

From the Webpush (with a payload) documentation, it seems that you should put all your data into the message, using the JSON.stringify() method, and retrieve it in the service worker with JSON.parse().

Server:

Webpush.payload_send({
  message:JSON.stringify({
    message: notification.message,
    url: notification.url,
    id: notification.id,
  }),
  endpoint: endpoint,
  p256dh: p256dh_key,
  vapid: vapid_keys,
  ttl: 24 * 60 * 60,
  auth: auth_key,
})

Client:

 event.waitUntil(
   self.registration.showNotification(title, {
   body: "New push notification",
   icon: "/images/[email protected]",
   tag:  "push-notification-tag",
   data: {
     url: JSON.parse(event.message).url
   }
})

Upvotes: 27

Related Questions