WebPushの効果的な実装方法と注意点

# はじめに
iOS 16.4からiOS safariでもWebPushが利用できるようになったこともあり、WebPushを導入するサービスが増えているのではないでしょうか？
ただ、__ページを開いた途端に通知権限をリクエストされた__ なんて経験はないでしょうか？
そのサイトからのお知らせが欲しいからPush通知を有効にするのに、どんなサイトかもわからないままだと許可もしづらいですよね。
また、いきなりだと反射的に拒否したり、拒否し続けてるとそもそもブラウザの仕組みで権限確認のポップアップが表示されないなんてことにも...
WebPushの活用が増えることを願ってこの記事を記載させていただきます。

# Push通知の実装について
今回は内部的な仕組みではなく __利用する際の実装__ の話がメインとなるため、WebPush自体の実装はAppvisorというサービスを利用します。

https://mb.app-visor.com/

こちらのサービスは無料でも利用することができるので、すぐに会員登録して利用開始することができるようになってます。

## iOSでのWebPushの要件
iOS safariではWebPushに対応したと言っても他と違ってさらに追加の要件が必要となります。
そちらを以下に簡単に記載させていただきます。
1. iOS16.4以上であること
1. PWA化されてホーム画面に配置されていること
1. ユーザの明示的なアクションによって通知許諾のポップアップを出すように実装すること

## WebPushを送るまでの簡単な流れ
1. ServiceWorkerを登録する
1. ブラウザから通知権限をユーザにリクエストする
1. バックエンドサービス(今回はAppvisor)にPush通知を送るために必要な情報を登録する
1. 上記で送られてきた情報を使ってバックエンドサービスからPush通知を配信する
1. ServiceWorkerがPush通知を受信してPush通知を表示する

## WebPush自体の基本の実装
AppvisorのSDK自体は管理画面からダウンロード済みのものとします。
1. 「appvisor.js」「sw-appvisor.js」をWebサイト上に配置してアクセスできるようにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252800/09029a15-ff19-54eb-c197-0787cbc83457.png)
1. HTMLファイル内からスクリプトを読み込む 
    ```index.html
    <script src="{YOUR_SITE_URL}/appvisor.js"></script>
    ```
1. SDKを初期化する
    ``` index.html
    <script>
      const { appvisor } = AppvisorSDK
      window.addEventListener("load", () => {
        appvisor.init({
          appVersion: '{YOUR_APP_VERSION}',
          appKey: '{YOUR_APP_KEY}'
        })
      })
      
      const registerBtn = document.getElementById("register")
      registerBtn.addEventListener("click", () => {
        var userConfirmed = confirm('Push通知サービスに登録しますか？');
        if (userConfirmed) {
          // 通知を表示する許可をリクエストする
          if (!appvisor.askForPermission()) {
            alert("Push通知を利用する場合、権限を許可をしてください")
            return
          }
          appvisor.register('{YOUR_VAPID_KEY}')
            .then(() => {
              alert("Push通知サービスへの登録が完了しました"); 
            }
            .catch((error) => {
              alert("Push通知サービスへの登録に失敗しました", error);
            })
        } else {
          alert('Push通知サービスの登録をキャンセルしました。');
        }  
      })
    </script>
    ```

# WebPush実装のポイント
## ポイント1 ユーザのアクションでポップアップを表示する
ページを開いた途端やスクロールをした時ではなく、何らかのボタンを押したタイミングでブラウザの通知権限のリクエストを送るようにしましょう。
![スクリーンショット 2024-07-17 10.48.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252800/f3010a58-d413-36b5-6db0-4883443e98ee.png)
特にこのようなユーザのアクションを求める実装はsafariに対応する上では __必須__ となります。

https://developer.apple.com/documentation/usernotifications/sending-web-push-notifications-in-web-apps-and-browsers#Enable-push-notifications-for-your-webpage-or-web-app

> Provide a method for the user to grant permission with a gesture, such as clicking or tapping a button.
ボタンをクリックまたはタップするなどの操作でユーザー自身が通知権限を許可する方法を提供します。

というようなことが公式ドキュメントに記載されていますね。

## ポイント2 事前に確認するポップアップを用意する
スマホアプリではよくあるパターンで、ウォークスルー等を使って

 __このアプリではこういうタイミングでPush通知を送ります。__
 __便利に使いたい場合はぜひ通知を許可してくださいね！__

というような旨の画面を表示した後で実際にOSの通知権限のリクエストダイアログを表示することが多いですが、
それをWebでも同じように行うイメージとなります。

ポイント1の2の手順も近いですが、デフォルトのアラートではなくそのサイト向けにデザインされたポップアップを用意すると、より効果的かと思います。


## ポイント3 セグメントを利用する
アプリと同様にWebでもセグメントが重要となってきます。
特にニュースサイト等では自分が気になるジャンルの情報の通知が欲しいですよね。

各サービスでもブラウザごとにどのユーザかを識別するIDとそこに追加の情報を紐づける仕組みが存在しているかと思うので、そちらを使ってカテゴリ等セグメントに使える情報を付与しましょう。
Appvisorでは以下のような実装となります。

``` index.html
<script>
  const likeCategory = "1"
  // 興味のあるカテゴリを「nameParamId」と設定します。パラメーターIDは管理画面から生成されます。
  const nameParamId = 1
  await appvisor.setUserProperty(name, nameParamId)
  // カスタマイズ属性をサーバへ送信する
  try {
      await appvisor.synchronizeUserProperties()
      // succeeded_messsage
  } catch(error) {
      // 失敗しました。
  }
</script>
```

# おわりに
ここまでお読みいただきありがとうございました。
safariがWebPushに対応するようになってから1年が経過し、iOS利用者の多くの方もWebPushを受け取れる環境になっているのではないでしょうか？
WebPush自体便利なものだと思いますので、上手な活用方法をこれからも探していければと思います。