2

I am having problems to implement notifications using firebase. The click event does not work. I am using the HTTP 1 version sending the bearer token.

{
  "message": {
    "token": "8888****usertoken****8888",
    "notification": {
      "title": "Background Message Title",
      "body": "Background message body"
    },
    "webpush": {
      "fcm_options": {
        "link": "https://dummypage.com"
      }
    }
  }
}

I have also tried click_action, action, and many other variations that just did not work.

I am using version 8.0.0

According to the documentation found on this link https://firebase.google.com/docs/cloud-messaging/js/send-multiple, I should be able to implement it using fcm_options.

I tried a workaround implementing messaging.onBackgroundMessage, but when I implement this method and use self.registration.showNotification, the notification is displayed twice. one triggered by the browse and the other by this code.

Registering self.addEventListener('notificationclick' only seems to work when I implement onBackgroundMessage.

I followed the documentation, but it is driving me crazy.

This is my service worker code:

importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-messaging.js');

var firebaseConfig = {
    apiKey: "xxxxxx",
    authDomain: "xxxxxxxx.firebaseapp.com",
    databaseURL: "https://xxxxxx.firebaseio.com",
    projectId: "xxx-xxx",
    storageBucket: "xxx-xxx.appspot.com",
    messagingSenderId: "222222222",
    appId: "1:2222:web:22222"
};
console.log("fire base messaging")

firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();


messaging.onBackgroundMessage(function (payload) {
    console.log("onBackgroundMessage", payload)
    var dataFromServer = payload.notification;
    var notificationTitle = dataFromServer.title;
    var notificationOptions = {
        body: dataFromServer.body,
        image: dataFromServer.image,
        data: {
            url: "https://google.com"
        }
    };
    return self.registration.showNotification(notificationTitle,
        notificationOptions);
});

////Code for adding event on click of notification
self.addEventListener('notificationclick', function (event) {
    console.log("notificationclick", event)
    var urlToRedirect = event.notification.data.url;
    event.notification.close();
    event.waitUntil(self.clients.openWindow(urlToRedirect));
});
Bruno Matavelli
  • 119
  • 1
  • 7

3 Answers3

9

Turns out I was passing an entire URL to webpush.fcm_options.link = "https://google.com", all I had to do was to pass only the relative path like webpush.fcm_options.link = "/mypage".

So the request to send would be like this:

{
  "message": {
    "token": "8888****usertoken****8888",
    "notification": {
      "title": "Background Message Title",
      "body": "Background message body"
    },
    "webpush": {
      "fcm_options": {
        "link": "/mypage" 
      }
    }
  }
}

I don't see in the docs say it is only the relative path. It even states that HTTPS is required. I spent a few hours on this one, I hope it helps somebody else.

https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#WebpushFcmOptions

Bruno Matavelli
  • 119
  • 1
  • 7
  • If you removed the data property from the request object, then what does your handleClick function look like, or is it even needed? Definitely struggling with this. – dev-jeff Feb 06 '21 at 15:13
  • 1
    Looks like the above inside the webpush property. The click handle will take you to whereever you defined in the link property. Just be aware that the link property needs to be just the relative path, you cannot specify the domain. You can pass data through the query string like /mypage?mydata=1&user=12345 – Bruno Matavelli Feb 08 '21 at 16:11
  • 1
    by doing this you don't need to define a function to handle the click, it is defined for you. It worked better for me because when I was specifying it, it was sometimes showing two messages and I had other problems as well. – Bruno Matavelli Feb 08 '21 at 16:19
  • It seems like it's working all the way as you describe, except that clicking the notification still doesn't do anything. I wonder if it's because I'm using the legacy HTTP API. – dev-jeff Feb 08 '21 at 19:01
  • 1
    I have tried the legacy and it did not work for me, probably because I was doing something wrong. I have the solution above working on the new API. I quickly went through the legacy API docs and I think you should look at click_action method.https://firebase.google.com/docs/cloud-messaging/http-server-ref – Bruno Matavelli Feb 09 '21 at 20:19
  • Thanks for the response. You are correct, and I posted my solution with the legacy API as a separate response in this thread. I also had to use an absolute URL because a background notification resulted in putting the name of the service worker file in between the host and the path of the URL for some reason. So my `click_action` was set to window.location.origin + '/' + router.resolve(route).href using Vue router. So for others it would be window.location.origin + '/' + – dev-jeff Feb 10 '21 at 00:31
  • Got an error `ValueError: WebpushFCMOptions.link must be a HTTPS URL.` when using relative link. Using path with domain, it just redirect to the browser and nothing more ..... – Youpsla Mar 15 '21 at 23:44
2

I was having the same issue. I added a notificationclick event handler. You can use the data param in the notification event to open a new tab or focus an already opened one.

The code you already have is fine, now adding the listener looks like this:

// messaging.onBackgroundMessage(...);

function handleClick (event) {
  event.notification.close();
  // Open the url you set on notification.data
  clients.openWindow(event.notification.data.url)
}
self.addEventListener('notificationclick', handleClick);

This resources might be helpful

Jonathan Morales Vélez
  • 3,030
  • 2
  • 30
  • 43
  • Hi Jonathan, thanks for your response. The 'notificationclick' does not trigger unless I raise my own event using 'self.registration.showNotification' and If I do the notification triggers twice. But I figured out what I was doing wrong I need to pass only the relative path to the fcm_options.link. not the entire URL as I was doing. I will update my question with what helped me. Thanks for your help. – Bruno Matavelli Nov 30 '20 at 15:14
  • 2
    Do you know why the notification triggers twice? I'm having the same problem. I even comment out the entire messaging.onBackgroundMessage((payload) =>... handler and I now get the first notification only, but doesn't have all the properties that want to add in that handler. – dev-jeff Feb 06 '21 at 17:22
0

Notifications are working using legacy API but unfortunately clicking the notification still does nothing. This is my code for sending the notification.

var notification = {
  'title': title,
  'body': body,
  'icon': 'hourglass.png',
  'click_action': router.resolve(route).href
}
var payload = {
  'notification': notification,
  // 'webpush': {
  //   'fcm_options': {
  //     'link': '/' + router.resolve(route).href
  //   }
  // }
}
if(registrationIds.length == 1) {
  payload['to'] = registrationIds[0]
} else if( registrationIds.length > 1){
  payload['registration_ids'] = registrationIds
}
return new Promise((resolve, reject) => {

  if (registrationIds.length) {
    fetch('https://fcm.googleapis.com/fcm/send', {
      'method': 'POST',
      'headers': {
        'Authorization': 'key=' + key,
        'Content-Type': 'application/json'
      },
      'body': JSON.stringify(payload)
    }).then(function(response) {
      resolve(true)
    }).catch(function(error) {
      console.error('sendNotification error', error);
      reject(false)
    })

  }
  else {
    console.log('This timer has no registered clients.')
    reject(false)

  }

})

Edit: I think most of my confusion stemmed from finding examples with the V1 API and mixing them up with the legacy API. I needed click_action instead of the fcm_options.link in the payload. I updated my code and is now working as intended.

dev-jeff
  • 173
  • 9