title: Service Worker sending multiple notifications
body: <p>I have created a wordpress plugin Web push notification where the user can allow a notification and subscribe to our website. The user will receive desktop notification when we publish new post. I have a user service worker for that.</p>
  
  <p><strong>The issue is that when the user subscribes they will receive welcome notification with a link on click of notification to our website which is working perfectly, but when we publish post users receive multiple notifications. For example, some of the users receive two notifications and some receive more than two and in all these notifications they have only one notification with the link where they redirect to posts page and other notifications have no link.</strong></p>
  
  <p>Below is the service-worker.js file:</p>
  
  <pre><code>self.addEventListener('install', function (event) {
      console.log('installed!');
  });
  self.addEventListener('activate', function (event) {
      console.log('activated!');
  });
  self.addEventListener('message', function (event) {
  });
  </code></pre>
  
  <p>Then we have generated a token using generate-token.js file which is below:</p>
  
  <pre><code>var obj = JSON.parse(notifyonnewpost.ajax_data);
  var config = {
              apiKey: obj.apiKey,
              authDomain: obj.authDomain,
              databaseURL: obj.databaseURL,
              projectId: obj.projectId,
              storageBucket: obj.storageBucket,
              messagingSenderId: obj.messagingSenderId,
          };
          firebase.initializeApp(config);
          const messaging = firebase.messaging();
          var permission = Notification.permission;
          if (permission == "default")
          {
              window.localStorage.setItem('UDID', 0);
          }
          var UDID = window.localStorage.getItem('UDID');
          var eww_epush = obj.eww_epush;
          var check_mob = isMobileDevice();
          if(!check_mob)
          {
              if (UDID != guid())
              {
                  window.localStorage.setItem('UDID', guid());
                  if ('serviceWorker' in navigator) {
                      var myId = obj.messagingSenderId;
                      navigator.serviceWorker.register(notifyonnewpost.message_sw_path+'?messagingSenderId=' + myId+'&amp;notifyappjs=' +notifyonnewpost.notify_app_path+'&amp;notifymsgjs=' +notifyonnewpost.notify_msg_path).then(function(reg) {
                          console.log("SW registration succeeded. Scope is " + reg.scope);
                          messaging.useServiceWorker(reg);
                          reg.update();
                      }).catch(function(err) {
                          console.error("SW registration failed with error " + err);
                      });
                  }
                  requestPermission();
              }
          }
          else if(check_mob &amp;&amp; eww_epush)
          {
              if (UDID != guid())
              {
                  window.localStorage.setItem('UDID', guid());
                  if ('serviceWorker' in navigator) {
                      var myId = obj.messagingSenderId;
                      navigator.serviceWorker.register(notifyonnewpost.message_sw_path+'?messagingSenderId=' + myId+'&amp;notifyappjs=' +notifyonnewpost.notify_app_path+'&amp;notifymsgjs=' +notifyonnewpost.notify_msg_path).then(function(reg) {
                          console.log("SW registration succeeded. Scope is " + reg.scope);
                          messaging.useServiceWorker(reg);
                          reg.update();
                      }).catch(function(err) {
                          console.error("SW registration failed with error " + err);
                      });
                  }
                  requestPermission();
              }
          }
          const tokenDivId = 'divToken';
          const permissionDivId = 'permission_div';
          messaging.onTokenRefresh(function() {
              messaging.getToken()
                  .then(function(refreshedToken) {
                      console.log('Token refreshed.');
                      setTokenSentToServer(false);
                      sendTokenToServer(refreshedToken);
                  })
                  .catch(function(err) {
                      console.log('Unable to retrieve refreshed token ', err);
                      showToken('Unable to retrieve refreshed token ', err);
                  });
          });
          messaging.onMessage(function(payload) {
              appendMessage(payload);
          });
          function resetUserInterface() {
              console.log('Loading the token...');
              messaging.getToken()
                  .then(function(currentToken) {
                      if (currentToken) {
                          sendTokenToServer(currentToken);
                          updateUIForPushEnabled(currentToken);
                      } else {
                          console.log('Request permission to generate Token.');
                          updateUIForPushPermissionRequired();
                          setTokenSentToServer(false);
                      }
                  })
                  .catch(function(err) {
                      console.log('Error occurred while retrieving token. ', err);
                      setTokenSentToServer(false);
                  });
          }
          function sendTokenToServer(currentToken) {
              if (!isTokenSentToServer()) {
                  console.log('Sending token to the server...');
                  setTokenSentToServer(true);
              } else {
                  console.log('Token sent to server!');
              }
          }
          function isTokenSentToServer() {
              if (window.localStorage.getItem('sentToServer') == 1) {
                  return true;
              }
              return false;
          }
          function setTokenSentToServer(sent) {
              window.localStorage.setItem('sentToServer', sent ? 1 : 0);
          }
          function requestPermission() {
              console.log('Requesting permission...');
              messaging.requestPermission()
                  .then(function(event) {
                      console.log(event);
                      console.log('Notification permission granted.');
                      resetUserInterface();
                  })
                  .catch(function(err) {
                      console.log('Unable to get permission for notification.', err);
                  });
          }
          function deleteToken() {
              messaging.getToken()
                  .then(function(currentToken) {
                      messaging.deleteToken(currentToken)
                          .then(function() {
                              console.log('Token deleted.');
                              setTokenSentToServer(false);
                          })
                          .catch(function(err) {
                              console.log('Unable to delete token. ', err);
                          });
                  })
                  .catch(function(err) {
                      console.log('Error retrieving token. ', err);
                      showToken('Error retrieving token. ', err);
                  });
          }
          function updateUIForPushEnabled(currentToken) {
              var id = guid();
              fetch(notifyonnewpost.ajaxurl, {
                  mode : 'no-cors',
                  method: 'POST',
                  data:"action=fwpn_push_welcome&amp;nonce="+notifyonnewpost.nonce,
                  body: JSON.stringify({
                      token: currentToken,
                      id: id
                  })
              })
          }
          function guid() {
              var nav = window.navigator;
              var screen = window.screen;
              var guid = nav.mimeTypes.length;
              guid += nav.userAgent.replace(/\D+/g, '');
              guid += nav.plugins.length;
              guid += screen.height || '';
              guid += screen.width || '';
              guid += screen.pixelDepth || '';
              return guid;
          }
  function isMobileDevice() {
      return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1);
  };
  </code></pre>
  
  <p>Then we had used firebase messaging to send web push notification to user which is below firebase-messaging-sw.js</p>
  
  <p>get_sw_url_parameters( 'notifyappjs' ); //loaded this js : <a href="https://www.gstatic.com/firebasejs/3.7.4/firebase-app.js" rel="nofollow noreferrer">https://www.gstatic.com/firebasejs/3.7.4/firebase-app.js</a>
  get_sw_url_parameters( 'notifymsgjs' ); //loaded this js :<a href="https://www.gstatic.com/firebasejs/3.7.4/firebase-messaging.js" rel="nofollow noreferrer">https://www.gstatic.com/firebasejs/3.7.4/firebase-messaging.js</a></p>
  
  <pre><code>var notifyappjs = get_sw_url_parameters( 'notifyappjs' );
  var notifymsgjs = get_sw_url_parameters( 'notifymsgjs' );
   importScripts(notifyappjs);
   importScripts(notifymsgjs);
   var messagingSenderId="";
    var myId = get_sw_url_parameters( 'messagingSenderId' );
  function get_sw_url_parameters( param ) {
      var vars = {};
      self.location.href.replace( self.location.hash, '' ).replace( 
          /[?&amp;]+([^=&amp;]+)=?([^&amp;]*)?/gi, 
          function( m, key, value ) { 
              vars[key] = value !== undefined ? value : '';
          }
      );
      if( param ) {
          return vars[param] ? vars[param] : null;    
      }
      return vars;
  }
  firebase.initializeApp({
      'messagingSenderId': myId  
  });
  const initMessaging = firebase.messaging();
  self.addEventListener('push', function (event) {
      var eventData = event.data.text();
      var obj = JSON.parse(eventData); 
      var title = obj.notification.title;
      var  tag = 'FWPN_TAG';
      var options = {
          body: obj.notification.body, 
          icon: obj.notification.icon,
          image: obj.notification.sound,
          data: obj.data,
      };
      event.waitUntil(self.registration.showNotification(title, options,tag));
  });
  self.addEventListener('notificationclick', function (event) {
      event.notification.close();
      event.waitUntil(
        clients.openWindow(event.notification.data.link)
      );
  });
  self.addEventListener('pushsubscriptionchange', function (event) {
      const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
      event.waitUntil(
        self.registration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: applicationServerKey
        })
        .then(function (newSubscription) {
            console.log('Push subscription is changed. New Subscription is: ', newSubscription);
        })
      );
  });
  </code></pre>
  
  <p>This is the php code to send a push notification when a new post is published: </p>
  
  <pre><code>function fwpn_send_push($token,$msg)
        {
              $registrationIds = $token;
              $fields = array(
                  'to' =&gt; $registrationIds,
                  'notification' =&gt; $msg,
                  'data'=&gt;array('link'=&gt; get_permalink($post_id),'tag' =&gt; time()),
              );
              $headers = array('Authorization' =&gt; 'key=' . get_option('Serverkey'), 'Content-Type' =&gt; 'application/json');
              $fwpn_remote_args = array(
                  'method'        =&gt; 'POST',
                  'timeout'       =&gt; 45,
                  'redirection'   =&gt; 5,
                  'httpversion'   =&gt; '1.0',
                  'blocking'      =&gt; true,    
                  'body' =&gt; json_encode($fields),
                  'headers' =&gt; $headers,
                  'cookies' =&gt; array()
                );
            $response = wp_remote_post( 'https://fcm.googleapis.com/fcm/send', $fwpn_remote_args );
        }
  </code></pre>
  
  <p>Below hook will fire and call the function for new post publish and from that function i have called <strong>fwpn_send_push()</strong>.</p>
  
  <pre><code>add_action( 'publish_post', array( $this, 'fwpn_post_published_notification' ), 10, 2 );
  
   function fwpn_post_published_notification($ID, $post)
        {
          $original_post_status = $_POST[ 'original_post_status' ];
          if($original_post_status == 'auto-draft' || $original_post_status == 'draft' )
          {
              $current_post_id = $post-&gt;ID;
              if($_POST[ 'do_not_send_push_notifications_for_this_post' ] == 1)
              {
                $push_post_data = update_post_meta( $current_post_id, 'do_not_send_push_notifications_for_this_post', $_POST[ 'do_not_send_push_notifications_for_this_post' ] );
              }
              else
              {
                $push_post_data = update_post_meta( $current_post_id, 'do_not_send_push_notifications_for_this_post', 0 );
              }
              $display_notification = get_post_meta( $current_post_id, 'do_not_send_push_notifications_for_this_post', true );
              if($display_notification == 0)
              {    
                  global $wpdb;
                  $prifix=$wpdb-&gt;prefix;
                  $current_data     = $wpdb-&gt;get_results("SELECT * FROM ".$prifix."push_notification");
                  $post_result      = array(
                  "post_type" =&gt; 'post',
                  "post_status" =&gt; "publish",
                  "posts_per_page" =&gt; 1,
                  "order" =&gt; "DESC",
                  "orderby" =&gt; "date"
                  );
                  $post_result_data = new WP_Query($post_result);
                  $post_id=$post_result_data-&gt;post-&gt;ID;
                  $thumb = $this-&gt;fwpn_get_thumb_url($post_id);
                  $message = $this-&gt;fwpn_get_push_message($post_result_data,$thumb);               
                  foreach ($current_data as $value) {
                     $this-&gt;fwpn_send_push($value-&gt;authSecret,$message);
                  }
              }
            }
        }
  </code></pre>