ユーザーの登録

まず、プッシュ メッセージを送信する権限をユーザーから取得します。その後、 PushSubscription を手に入れよう。

これを行う JavaScript API はかなり簡単なので、少しだけ 見ていきます

機能検出

まず、現在のブラウザが実際にプッシュ メッセージングに対応しているかどうかを確認する必要があります。「新規顧客の獲得」目標を push は 2 つのシンプルなチェックでサポートされます。

  1. navigatorserviceWorker を確認します。
  2. windowPushManager を確認します。
if (!('serviceWorker' in navigator)) {
  // Service Worker isn't supported on this browser, disable or hide UI.
  return;
}

if (!('PushManager' in window)) {
  // Push isn't supported on this browser, disable or hide UI.
  return;
}

ブラウザのサポートは、Service Worker と Service Worker と プッシュ メッセージングでは、検出機能だけでなく、 段階的に改善されます

Service Worker を登録する

Feature Detection では、Service Worker と Push の両方がサポートされていることがわかっています。次のステップ 「Register」です。使用します。

Service Worker を登録すると、その Service Worker ファイルの場所をブラウザに伝えます。 ファイルは単なる JavaScript ですが、ブラウザは「アクセスを許可」します。Service Worker に push を含む厳密に言えば、ブラウザはファイルを Service Worker で実行します。 できます。

Service Worker を登録するには、navigator.serviceWorker.register() を呼び出して 追加します。たとえば、次のようにします。

function registerServiceWorker() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      console.log('Service worker successfully registered.');
      return registration;
    })
    .catch(function (err) {
      console.error('Unable to register service worker.', err);
    });
}

この関数により、ブラウザに Service Worker ファイルとその保存場所が伝えられます。イン この例では、Service Worker ファイルは /service-worker.js にあります。ブラウザのバックグラウンドで register() を呼び出した後、次の処理を行います。

  1. Service Worker ファイルをダウンロードします。

  2. JavaScript を実行します。

  3. すべてが正しく実行され、エラーがなければ、register() によって Promise が返されます。 解決します。なんらかのエラーがある場合、Promise は拒否されます。

register() が拒否された場合は、Chrome DevTools で JavaScript に入力ミスやエラーがないか再確認してください。

register() が解決されると、ServiceWorkerRegistration が返されます。使用するのは PushManager API にアクセスします。

PushManager API ブラウザの互換性

対応ブラウザ

  • Chrome: 42。 <ph type="x-smartling-placeholder">
  • Edge: 17。 <ph type="x-smartling-placeholder">
  • Firefox: 44。 <ph type="x-smartling-placeholder">
  • Safari: 16。 <ph type="x-smartling-placeholder">

ソース

権限をリクエストしています

Service Worker の登録が完了し、ユーザーをサブスクライブする準備ができました。次のステップでは、 push メッセージを送信するための権限をユーザーに付与する必要があります。

権限を取得するための API は比較的シンプルですが、デメリットは、 この API は最近、コールバックの受け取りから Promise を返すものに変更されました。「 現在の API でどのバージョンの API が 両方を実装して処理する必要があります。

function askPermission() {
  return new Promise(function (resolve, reject) {
    const permissionResult = Notification.requestPermission(function (result) {
      resolve(result);
    });

    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  }).then(function (permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error("We weren't granted permission.");
    }
  });
}

上記のコードでは、重要なスニペットが Notification.requestPermission()。このメソッドは、ユーザーにプロンプトを表示します。

パソコンとモバイルの Chrome での権限プロンプト。

ユーザーが [許可]、[ブロック] を押すか、単に閉じるという操作で権限プロンプトを操作すると、 結果は文字列 'granted''default'、または 'denied' として返されます。

上記のサンプルコードでは、askPermission() によって返される Promise は、 そうでない場合は、Promise が拒否されるエラーがスローされます。

対処が必要なエッジケースの 1 つは、ユーザーが [ブロック] をクリックした場合です。] ボタンを離します。もし ウェブアプリがユーザーに権限を再度求めることはできなくなります。データ アナリストは、 手動で「ブロックを解除」するアプリの権限状態を変更して、アプリのパフォーマンスを [設定]パネルでユーザーに許可を求める方法やタイミングは慎重に検討し、 ブロックをクリックすると その選択を簡単に取り消すことはできないためです

幸いなことに、ほとんどのユーザーは、 権限がリクエストされる理由を知っている

人気のあるサイトがどのように許可を求めるかについては後ほど説明します。

PushManager でユーザーを登録する

Service Worker を登録し、権限を取得したら、次の方法でユーザーをサブスクライブします。 registration.pushManager.subscribe() を呼び出しています。

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

subscribe() メソッドを呼び出すときに、options オブジェクトを渡します。このオブジェクトは、 必須のパラメータと省略可能なパラメータです。

渡すことができるすべてのオプションを見てみましょう。

userVisibleOnly オプション

ブラウザに push が初めて追加されたとき、デベロッパーに プッシュ メッセージを送信したり、通知を非表示にしたりできます。これは一般にサイレント モードと呼ばれ、 push します。これは、バックグラウンドで何かが起きたことにユーザーが気付かなかったためです。

懸念事項は、デベロッパーが ユーザーに知られることなく継続的に実行されます

このシナリオを回避し、仕様作成者がこれをサポートする最適な方法を検討する時間を確保するために、 userVisibleOnly オプションが追加され、値 true が渡されることがシンボリックな機能です。 プッシュが発生するたびにウェブアプリが通知を表示することを、ブラウザと合意します。 (サイレント プッシュなし)。

現時点では、true の値を渡す必要があります。ここに userVisibleOnly キーまたは false を渡すと、次のエラーが発生します。

現在 Chrome では、サブスクリプションの Push API のみサポートしています。 表示することもできます。これを指定するには、 代わりに pushManager.subscribe({userVisibleOnly: true}) を使用してください。詳しくは、 詳しくは https://goo.gl/yqv4Q4 をご覧ください。

現在のところ、Chrome では包括的なサイレント プッシュは実装されないようです。代わりに 仕様作成者は、ウェブアプリで特定のトラフィックを ウェブアプリの使用状況に基づくサイレント プッシュ メッセージ数。

applicationServerKey オプション

「アプリケーション サーバーキー」について簡単に触れましたが、説明しました。"アプリケーション サーバーキー"push サービスにより、ユーザーを登録するアプリケーションを識別し、 同じアプリケーションがそのユーザーにメッセージを送信していることを確認します。

アプリケーション サーバーの鍵は、アプリケーションに固有の公開鍵と秘密鍵のペアです。 秘密鍵はアプリケーションに対して秘密にする必要があり、公開鍵は できます。

subscribe() 呼び出しに渡される applicationServerKey オプションは、アプリケーションの ] キーを押します。ブラウザはユーザーのサブスクライブ時にこれをプッシュ サービスに渡します。つまり、 サービスがアプリケーションの公開鍵をユーザーの PushSubscription に結び付けることができます。

次の図に、これらのステップを示します。

  1. ウェブアプリがブラウザに読み込まれ、subscribe() を呼び出して一般公開の URL を渡します。 アプリケーション サーバー キー。
  2. ブラウザは、エンドポイントを生成する push サービスにネットワーク リクエストを行い、 このエンドポイントをアプリケーションの公開鍵に関連付けて、エンドポイントを できます。
  3. ブラウザはこのエンドポイントを PushSubscription に追加します。これにより、 subscribe() Promise。

サブスクライブで使用されている公開アプリケーション サーバーキーのイラスト
メソッドを呼び出します。

後で push メッセージを送信するときは、Authorization ヘッダーを作成する必要があります これには、アプリケーション サーバーの秘密鍵で署名された情報が含まれます。Google push サービスが push メッセージの送信リクエストを受信すると、この署名付き Authorization ヘッダーを検証できる 公開鍵を検索します。署名が push サービスは、Cloud KMS 鍵を持つアプリケーション サーバーから 一致する秘密鍵です。これは基本的には 誰かにデータが 送信されないよう メッセージをアプリケーションのユーザーに配信できます。

アプリケーション サーバーの秘密鍵が、
メッセージ

厳密に言えば、applicationServerKey は省略可能です。ただし、 では必須ですが、他のブラウザでは、 実現します。Firefox では省略可能です。

アプリケーション サーバー キーの内容を定義する仕様は、 VAPID 仕様をご覧ください。 「アプリケーション サーバー キー」または 「VAPID キー」を使用する方法もありますが、同じものです。

アプリケーション サーバーキーの作成方法

アプリケーション サーバーキーの公開 / 非公開のセットは、 web-push-codelab.glitch.me または web-push コマンドライン 鍵を生成するには、次の操作を行います。

    $ npm install -g web-push
    $ web-push generate-vapid-keys

アプリケーションに対してこれらのキーを作成する必要があるのは 1 回だけで、 使用します。(うん、そう言ったよ)

権限と subscribe()

subscribe() を呼び出すと、副作用が 1 つあります。ウェブアプリに subscribe() を呼び出したときに通知を表示すると、ブラウザは 自動的に作成されます。これは UI がこのフローに対応している場合に便利ですが、 Notification.requestPermission() API を使用してください(ほとんどのデベロッパーはこれでしょう)。 使用します。

PushSubscription とは

subscribe() を呼び出し、いくつかのオプションを渡すと、次の Promise を返します。 PushSubscription のコードは次のようになります。

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

PushSubscription オブジェクトには、push の送信に必要なすべての情報が含まれています。 そのユーザーにメッセージが送信されます。JSON.stringify() を使用して内容を出力すると、次のようになります。 次のとおりです。

    {
      "endpoint": "https://some.pushservice.com/something-unique",
      "keys": {
        "p256dh":
    "BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
        "auth":"FPssNDTKnInHVndSTdbKFw=="
      }
    }

endpoint は、push サービスの URL です。push メッセージをトリガーするには、POST リクエストを行います。 追加します。

keys オブジェクトには、push メッセージで送信されるメッセージ データの暗号化に使用する値が含まれます。 (これについては後ほど説明します)。

期限切れにならないよう定期的に再度定期購入する

プッシュ通知に登録すると、多くの場合、nullPushSubscription.expirationTime を受け取ります。理論上、これは定期購入が期限切れになることはないことを意味します(定期購入が期限切れになる正確な時点を示す DOMHighResTimeStamp を受け取る場合とは対照的)。しかし実際には、プッシュ通知を長時間受信していない場合や、ユーザーがプッシュ通知権限を持つアプリを使用していないことをブラウザが検出した場合などには、ブラウザでサブスクリプションが期限切れになるのが一般的です。これを防ぐパターンの 1 つは、次のスニペットに示すように、通知を受信するたびにユーザーを再登録することです。そのためには、ブラウザで定期購入が自動的に期限切れにならないよう、十分な頻度で通知を送信する必要があります。定期購入が期限切れにならないように、ユーザーに無意識にスパム行為を仕掛ける場合と、正当な通知のメリットとデメリットを慎重に比較検討する必要があります。結局のところ、ユーザーが通知登録を忘れてしまった状態からユーザーを守るために、ブラウザと戦うことはやめましょう。

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

サーバーに購読を送信する

push サブスクリプションを作成したら、それをサーバーに送信する必要があります。また、どのように ただし、JSON.stringify() を使用して、必要なデータを subscription オブジェクト。または 1 つの nginx ウェブサーバーを 手動で実行することもできます。

const subscriptionObject = {
  endpoint: pushSubscription.endpoint,
  keys: {
    p256dh: pushSubscription.getKeys('p256dh'),
    auth: pushSubscription.getKeys('auth'),
  },
};

// The above is the same output as:

const subscriptionObjectToo = JSON.stringify(pushSubscription);

サブスクリプションの送信は、次のようにウェブページで実行します。

function sendSubscriptionToBackEnd(subscription) {
  return fetch('/api/save-subscription/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(subscription),
  })
    .then(function (response) {
      if (!response.ok) {
        throw new Error('Bad status code from server.');
      }

      return response.json();
    })
    .then(function (responseData) {
      if (!(responseData.data && responseData.data.success)) {
        throw new Error('Bad response from server.');
      }
    });
}

ノードサーバーはこのリクエストを受け取り、後で使用できるようにデータベースにデータを保存します。

app.post('/api/save-subscription/', function (req, res) {
  if (!isValidSaveRequest(req, res)) {
    return;
  }

  return saveSubscriptionToDatabase(req.body)
    .then(function (subscriptionId) {
      res.setHeader('Content-Type', 'application/json');
      res.send(JSON.stringify({data: {success: true}}));
    })
    .catch(function (err) {
      res.status(500);
      res.setHeader('Content-Type', 'application/json');
      res.send(
        JSON.stringify({
          error: {
            id: 'unable-to-save-subscription',
            message:
              'The subscription was received but we were unable to save it to our database.',
          },
        }),
      );
    });
});

サーバー上の PushSubscription の詳細を確認したら、ユーザーを送信します。 いつでもメッセージを受け取れます。

期限切れにならないよう定期的に再度定期購入する

プッシュ通知に登録すると、多くの場合、nullPushSubscription.expirationTime を受け取ります。理論上、これは定期購入が期限切れになることはないことを意味します(定期購入が期限切れになる正確な時点を示す DOMHighResTimeStamp を受け取る場合とは対照的)。しかし実際には、プッシュ通知を長時間受信していない場合や、ユーザーがプッシュ通知権限を持つアプリを使用していないことをブラウザが検出した場合などは、ブラウザで引き続き購読が期限切れになるのが一般的です。これを防ぐパターンの 1 つは、次のスニペットに示すように、通知を受信するたびにユーザーを再登録することです。そのためには、ブラウザで定期購入が自動的に期限切れにならないよう、十分な頻度で通知を送信する必要があります。正当な通知のメリットとデメリットについて、定期購入が期限切れにならないようにユーザーにスパム行為をすることと、慎重に比較検討する必要があります。結局のところ、ユーザーが通知登録を忘れてしまった状態からユーザーを守るために、ブラウザと戦うことはやめましょう。

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

よくある質問

この時点でよくある質問をいくつかご紹介します。

ブラウザが使用するプッシュ サービスを変更できますか?

いいえ。push サービスはブラウザによって選択されます。 subscribe() 呼び出しを行うと、ブラウザは push サービスにネットワーク リクエストを行います。 PushSubscription を構成する詳細を取得します。

ブラウザごとに異なる Push Service を使用しているのに、API が異なるのでしょうか?

すべての push サービスで同じ API が使用されます。

この共通の API は ウェブプッシュ プロトコル ネットワーク リクエストの push メッセージをトリガーするために必要な手順の数です。

パソコンでユーザーを登録した場合、そのユーザーのスマートフォンでも登録されますか?

いいえ。ユーザーは、希望するブラウザごとに push に登録する必要がある メッセージを受信しますなお ユーザーが各デバイスに権限を付与する場合です。

次のステップ

Codelab