How to add analytics for Push notifications

2020-05-28 11:42发布

问题:

I'm working on progressive web app, and I want to implement analytics for Push notifications.

How can I add analytics for push notifications so that I'll be able to track and record how many people clicked on notification and how many people close that notification without clicking on it.

回答1:

I've written a small chunk of code to use Google analytics for analytics and it works fairly well.

Dumped notes here: https://gauntface.com/blog/2016/05/01/push-debugging-analytics


The way I've done this is the post mentioned above:

In the service worker I import a javascript file that does the tracking for me, set the analytics ID and then in the appropriate events call the tracking. Look for self.analytics.trackEvent:

importScripts('./scripts/analytics.js');

self.analytics.trackingId = 'UA-77119321-2';

self.addEventListener('push', function(event) {
  let notificationTitle = 'Hello';
  const notificationOptions = {
    body: 'Thanks for sending this push msg.',
    icon: './images/icon-192x192.png',
    tag: 'simple-push-demo-notification'
  };

  // Important to trigger analytics asynchronously with logic
  // to show notification
  event.waitUntil(
    Promise.all([
      self.analytics.trackEvent('push-received'),
      self.registration.showNotification('Hello', notificationOptions)
    ])
  );
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  // Important to trigger analytics asynchronously with logic
  // to do other work (i.e. open window)
  event.waitUntil(
    Promise.all([
      self.analytics.trackEvent('notification-click'),
      clients.openWindow('https://gauntface.github.io/simple-push-demo/')
    ])
  );
});

The code to do the actual tracking calls to Google Analytics Measurements Protocol is shown below. The API is painfully simplistic, so the payloadData are the attributes analytics expects and I generate a string of these parameters in the format the API expects, filtering out empty / null values:

class Analytics {
  trackEvent(eventAction, eventValue) {
    if (!this.trackingId) {
      console.error('You need to set a trackingId, for example:');
      console.error('self.analytics.trackingId = \'UA-XXXXXXXX-X\';');

      // We want this to be a safe method, so avoid throwing Unless
      // It's absolutely necessary.
      return Promise.resolve();
    }

    if (!eventAction && !eventValue) {
      console.warn('sendAnalyticsEvent() called with no eventAction or ' +
      'eventValue.');
      return Promise.resolve();
    }

    return self.registration.pushManager.getSubscription()
    .then(subscription => {
      if (subscription === null) {
        // The user has not subscribed yet.
        throw new Error('No subscription currently available.');
      }

      const payloadData = {
        // GA Version Number
        v: 1,
        // Client ID
        cid: subscription.endpoint,
        // Tracking ID
        tid: this.trackingId,
        // Hit Type
        t: 'event',
        // Data Source
        ds: 'serviceworker',
        // Event Category
        ec: 'serviceworker',
        // Event Action
        ea: eventAction,
        // Event Value
        ev: eventValue
      };

      const payloadString = Object.keys(payloadData)
      .filter(analyticsKey => {
        return payloadData[analyticsKey];
      })
      .map(analyticsKey => {
        return `${analyticsKey}=` +
          encodeURIComponent(payloadData[analyticsKey]);
      })
      .join('&');

      return fetch('https://www.google-analytics.com/collect', {
        method: 'post',
        body: payloadString
      });
    })
    .then(response => {
      if (!response.ok) {
        return response.text()
        .then(responseText => {
          throw new Error(
            `Bad response from Google Analytics ` +
            `[${response.status}] ${responseText}`);
        });
      }
    })
    .catch(err => {
      console.warn('Unable to send the analytics event', err);
    });
  }
}

if (typeof self !== 'undefined') {
  self.analytics = new Analytics();
}

You can find all of this on: https://github.com/gauntface/simple-push-demo



回答2:

An option, that I'm using in my WordPress web-push plugin, is to add a query argument to the URLs opened via notifications (see this code). This way, you can know how many times people click on notifications.

About the number of people that close notifications, it's unfortunately not possible to know. There's a notificationclose event, but it is only triggered for persistent notifications.



回答3:

At Pushpad the notification url is a redirect page that tracks the opening and then redirects to the target url.

For example if the target url is http://example.com/target your notification url that is opened on click should be http://example.com/redirect?url=/target.

At the moment there is no way to track when the notification is dismissed.

Update (June 2016): others have pointed out that in the specs there's a notificationclose event. However I haven't tested browser support (currently this event is not listed on MDN for example). Beside that I fear that this event can also be triggered when the user clicks the notification (since the notification gets closed) - the spec is not clear about that.