当サイトを最適な状態で閲覧していただくにはブラウザのJavaScriptを有効にしてご利用下さい。
JavaScriptを無効のままご覧いただいた場合には一部機能がご利用頂けない場合や正しい情報を取得できない場合がございます。
承知しました
本サイトではWebサイトのエクスペリエンスを向上させるために、Cookieを使用しています。Cookieはブラウザの設定から無効にできます。本サイトで使用するCookieについては、プライバシーポリシーをご確認ください。

Blog

ブログ

開発者向け

Kontentからのプッシュ通知の送信

By Eric Dugre  

プッシュ通知を送信することは、プロモーション、興味のあるアイテム、ショッピングカートに残したものなどを顧客に知らせるための優れた方法です。ただし、編集者がプッシュ通知を送信したい場合は、コードを知らなくてもこれを実現する簡単な方法が必要になります。

この投稿では、Kentico Kontentでコンテンツタイプを設定します。これを使用して、編集者は新しいプッシュ通知を作成できます。これらのアイテムが公開されると、アプリケーションはすべての訪問者にプッシュ通知を自動的に送信します。 さらに、コンテンツスケジューリング機能を使用して、将来の特定の時間にプッシュ通知を送信することができます。

アプリケーションのセットアップ

このブログ投稿では、 GitHubのExpressJSサンプルプロジェクトを参照します。 Nodeプロジェクトであるため、このWebプッシュをインストールして通知を送信します。通常、プッシュ通知はクライアント側でJavaScriptを使用して訪問者に送信されますが、このライブラリを使用すると、KontentからWebhookを受信したときにサーバーからプッシュ通知を送信できます。

 npm i web-push -g

Webプッシュがインストールされている状態で、アプリケーションがプッシュ通知を送信するために必要なVAPIDキーを生成します。 VAPIDキーは、プッシュサービスを使用してアプリケーションを識別するために使用され、VAPIDキーがないと、Webプッシュを使用できません。これらのキーをどこかのファイルに保存します。この記事の後半で使用します。

 web-push generate-vapid-keys

上で述べたように、KontentからのWebhookに反応してプッシュ通知を送信します。 Webhookは、コンテンツアイテムが公開されているなど、何かが変更されたときにアプリケーションに送信できるメッセージです。プロセスは次のようになります。

Kentico Kontent


アプリケーションがWebhookPOSTを受信したら、署名を使用してリクエストがKontentから送信されていることを確認する必要があります。 Webhookの生のJSONボディを受け取り、署名を確認する必要があるため、この時点でボディパーサーをインストールします。

 npm i body-parser

ExpressがJSONデータにこのパーサーを使用するようにするには、 app.jsを変更します。

 const bodyParser = require('body-parser');//app.use(express.json()); // original code added automatically to Express- comment or remove this lineapp.use(bodyParser.raw({type:'application/json'})) // add this line

訪問者が通知を購読できるようにする

まず、ブラウザからプッシュ通知を受信するための訪問者の許可が必要です。これは、ブラウザと通信するために、プレーンJavaScriptでクライアント側で実行する必要があります。アプリケーションのメインレイアウトファイルでは、このロジックを追加できる「メイン」JavaScriptファイルをレンダリングしている可能性があります。 Expressサンプルアプリケーションでは、 client.jsを/views/layout.pug内でレンダリングしているため、JavaScriptをそのファイルに追加します。

 script(type='text/javascript', src='/scripts/client.js')

許可を得るための最初のステップは、ブラウザがプッシュ通知を送信できるかどうかを確認することです。プッシュ通知は安全なSSL接続でのみサポートされるため、アプリケーションはHTTPSで実行する必要があることに注意してください。次の行は、スクリプトが読み込まれるとすぐに実行され、serviceWorkerがブラウザーで使用可能かどうかを確認し、使用可能な場合は独自の実行関数を呼び出します。

 if ('serviceWorker' in navigator) { run().catch(error => console.error(error));}

ここで、スクリプトをserviceWorkerに非同期で登録し、独自のコールバックメソッドを渡すrun関数を定義します。

const run = async() => { await navigator.serviceWorker .register(`/scripts/worker.js`, {scope: '/scripts/'}) .then(waitRegistration);}

/ public / scriptsディレクトリに独自のサービスワーカーファイルworker.jsを登録していることに注意してください。これは、サーバーからプッシュ通知が送信されたときに呼び出されるファイルです。これでファイルを作成できますが、空白のままにします。訪問者の許可を求める前に、登録が完了していることを確認する必要があります。 waitRegistration関数は、イベントリスナーを使用してserviceWorkerの状態が「アクティブ化」されるまで待機してから、 subscribeForPush関数を呼び出します。

 const waitRegistration = (reg) => { var serviceWorker; if (reg.installing) { serviceWorker = reg.installing; } else if (reg.waiting) { serviceWorker = reg.waiting; } else if (reg.active) { serviceWorker = reg.active; } if (serviceWorker) { if (serviceWorker.state == 'activated') { subscribeForPush(reg); } serviceWorker.addEventListener('statechange', function(e) { if (e.target.state == 'activated') { subscribeForPush(reg); } }); }}

すべての設定が完了したら、最終的に訪問者に許可を求めることができます。 subscribeForPushは、subscribe関数を使用してこれを実行し、権限がある場合、関数はPushSubscriptionオブジェクトを返します。訪問者をサブスクライブするには、この記事の冒頭で生成した公開VAPIDキーが必要です。キーをJavaScriptファイルに直接追加します。

 const publicVapidKey = 'BDRkdCmrfqQ6F-PhAA1AN68jJqHQWARNyxSWFOh1YMpKgju6tHG_dLVxJTgLTXfkXqYFL1VTfcDitw1k4n34IZ8';

これで、subscribeForPush関数で使用できます。

 const subscribeForPush = async (reg) => { await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicVapidKey) }) .then((sub) => { //Store subscription somewhere });}const urlBase64ToUint8Array = (base64String) => { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));}

訪問者が購読すると、購読に関する重要な情報を受け取り、どこかに保存する必要があります。

  • エンドポイント-プッシュサービスを指すランダム化されたURL(例:https://fcm.googleapis.com/fcm/send/csI_R3I7MN [...])
  • p256dh-サブスクリプションキー
  • auth-サブスクリプションシークレット

Expressプロジェクトでは、データを/ subscribeエンドポイントにPOSTし、 ここでSQLiteデータベースに保存していますが、この情報はどこにでも保存できます(たとえば、テスト用のアプリケーションメモリ、テキストファイルなど)。サーバーなど)。

Kontentでのプロジェクトの構成

通知を希望する訪問者のリストを作成したので、通知を自分で設計できます。プッシュ通知は、特定のコンテンツアイテムがKontentで公開されるたびにトリガーされるため、プロジェクトに移動して、「プッシュ通知」と呼ばれる新しいコンテンツタイプを作成します。

Kentico Kontent

このコンテンツタイプには、プッシュ通知の送信に必要な要素が含まれます。 プッシュ通知を送信するためのドキュメントで、少なくともタイトル、本文、およびアイコンが必要であることがわかります。オプションで、通知がクリックされたときにデバイスを振動させてURLを開くこともできるため、コンテンツタイプで作成する要素は次のとおりです。

  • タイトル:テキスト
  • 本文:テキスト
  • アイコン:アセット
  • バイブレーション:複数選択(単一値のチェックボックス「はい」)
  • url :テキスト

このタイプのアイテムが公開されたときにプッシュ通知を送信する必要があるため、 Webhookページに移動して、「プッシュ通知」と呼ばれる新しいWebhookを作成できます。 [ URLアドレス]フィールドに、POSTリクエストをインターセプトするエンドポイント(https://mysite.com/pushなど)を含むWebサイトのURLを入力します(次のセクションで作成します)。また、後で使用するためにシークレットをコピーします。 [監視するコンテンツアイテムのイベント]ドロップダウンで、[公開]を選択し、Webhookを保存します。

Kentico Kontent

Webhookの検証

アプリケーションでWebhookのPOSTリクエストを受信するエンドポイントを作成します。 Expressでは、app.jsに/ pushエンドポイントを登録します。

 app.use('/', require('./routes/push'));

次に、POSTリクエストに応答するためのプッシュルートを作成します。

 router.post('/push', (req, res) => { //...}

すべてのWebhook通知には、リクエストがKontentから送信されていることを確認するための署名があります。署名は、Webhookシークレットとリクエストの本文のハッシュです。署名の詳細についてはこちらをご覧ください。JavaScriptで署名を確認する例についてはこちらをご覧ください

POSTリクエストのヘッダーの署名を検証するには、前にコピーしたWebhookシークレットを/ pushエンドポイントのconst として追加するか、環境変数を使用する必要があります。署名を検証する新しい関数を作成します。

 const crypto = require('crypto');const webhookSecret = '';const hasValidSignature = (body, signature) => {const computedSignature = crypto.createHmac('sha256', webhookSecret).update(body).digest();return crypto.timingSafeEqual(Buffer.from(signature, 'base64'), computedSignature);}router.post('/push', (req, res) => { //...}

/ pushハンドラーで、req.headersオブジェクトの本体と署名を渡してhasValidSignature関数を呼び出します。

 app.post('/push', (req, res) => {if(hasValidSignature(req.body, req.headers['x-kc-signature'])) {res.status(200).send('Success');}else {res.status(403).send('Invalid signature');}});

これで、Webhookをテストして、200応答が正常に受信されることを確認できます。 Kontentでコンテンツアイテムを公開し、POSTリクエストがアプリケーションに送信されるのを待ちます。 KontentのWebhookページで、Webhookの横に成功したことを示す緑色の点が表示されます。

Kentico Kontent

Webhookが適切に検証されたら、KontentがWebhook通知の本文で送信したデータの読み取りに進むことができます。

Webhookの処理

JavaScriptSDKのDeliveryAPIを使用して、Kontentから新しく公開されたコンテンツアイテムを取得します。このセクションを開始する前に、Deliveryクライアントをインストールし、/ pushエンドポイントでクライアントをインスタンス化するための手順に従います。

 const { DeliveryClient } = require('@kentico/kontent-delivery');const deliveryClient = new DeliveryClient({ projectId: 'your-project-ID', globalQueryConfig: { waitForLoadingNewContent: true }});

waitForLoadingNewContentを使用したい Deliveryから最新のデータを取得し、キャッシュされる可能性のあるものを回避できるように、ここでオプションを選択します。 Webhook通知で提供された情報を見て、コンテンツアイテムから値を取得するために何が必要かを判断しましょう。 ワークフローWebhook通知の本文は、以前の非ワークフローWebhookとは異なります。次のようになります。

 'data': {'items': [{'item': {'id': '65f05e0f-40c3-436b-a641-e2d4cae16e46'},'language': {'id': '00000000-0000-0000-0000-000000000000'},'transition_from': {'id': 'eee6db3b-545a-4785-8e86-e3772c8756f9'},'transition_to': {'id': '03b6ebd3-2f49-4621-92fd-4977b33681d1'}}]}

Itemオブジェクトには、公開されたコンテンツアイテムのIDが含まれています。このWebhookはそのワークフローステップに対してのみトリガーされるため、 transition_fromまたはtransition_toの値について心配する必要はありません。公開されたコンテンツアイテムの値を使用してプッシュ通知を送信するには、この応答からコンテンツアイテムのIDを抽出するだけで済みます。

このプロセスを開始するには、ロジックを含む新しい関数を作成し、署名が検証された後にそれを呼び出します。

 app.post('/webhook', (req, res) => {if(hasValidSignature(req.body, req.headers['x-kc-signature'])) {processWebhook(JSON.parse(req.body));//...const processWebhook = (body) => {}

新しいprocessWebhook関数では、応答のJSON本文からアイテムIDを取得できます。

 const processWebhook = (body) => { const updatedVariantItemID = body.data.items[0].item.id; //...}

コンテンツアイテムIDを使用すると、Delivery APIで利用可能なフィルタリングオプションを使用して、探している正確なコンテンツアイテムを見つけることができます。リクエストからObservableを作成し、サブスクライブし、結果を受け取ったらサブスクライブを解除します。

 const sub = deliveryClient.items() .equalsFilter('system.id', updatedVariantContentID) .toObservable() .subscribe(result => { sub.unsubscribe(); //... });

続行する前に、正しいコンテンツアイテムを取得したことを確認しましょう。 items関数はアイテムの配列を返しますが、この場合はアイテムが1つだけである必要があります。 result.items配列をチェックして、少なくとも1つのアイテムがあることを確認し、そのアイテムが「push_notification」コンテンツタイプである場合にのみ続行します。

 if(result.items.length > 0 && result.items[0].system.type == 'push_notification') { sendPush(result.items[0]); }

すべてが良好に見える場合は、コンテンツアイテムを次のセクションで作成する新しい関数sendPushに渡します。

プッシュ通知の送信

必要な情報が得られたので、実際にプッシュ通知を送信するようにsendPush関数を定義しましょう。コンテンツアイテムオブジェクトがどのように見えるかの例は、 こちらのドキュメントで確認できます。後でworker.jsファイルで使用されるプッシュ通知のペイロードを作成することから始めます。

 const sendPush = function(item) { const payload = JSON.stringify({ title: item.title.value, body: item.body.value, icon: item.icon.value[0].url, vibrate: item.vibrate.value.length > 0, url: item.url.value }); //...

Webプッシュを使用するには、最初に、以前に生成された公開鍵と秘密鍵を使用してVAPID資格情報を設定します。

 const webpush = require('web-push');webpush.setVapidDetails('mailto:yourmail@yoursite.com', publicVapidKey, privateVapidKey);

次に、通知をサブスクライブした訪問者ごとに、WebプッシュのsendNotification()関数を呼び出す必要があります。すべてのサブスクライバーを取得してから、リストをループします。 Expressアプリケーションでは、SQLiteデータベースからすべてのサブスクリプションを取得し、レコードからWebプッシュに必要なサブオブジェクトを作成します。

 const dao = new AppDAO();dao.getAllSubscriptions().then((rows) => { rows.forEach((row) => { let sub = { endpoint: row.endpoint, keys: { p256dh: row.p256dh, auth: row.auth } }; }); //Send push...});

サブスクリプションオブジェクトを作成した後、WebプッシュのsendNotificationを呼び出して、サブスクリプションとペイロードを渡すことができます。

 webpush.sendNotification(sub, payload).catch(response => { if(response.statusCode === 410) { //Subscription expired or removed- delete from db dao.deleteSubscription(sub); }});

リクエストが410ステータスを返す場合、サブスクリプションは期限切れであるか、手動で取り消されているため、データベースから削除する必要があります。

ServiceWorkerファイルの仕上げ

ほぼ完了です!作成したworker.jsファイルを覚えていますか?これは実際のサービスワーカー自身であり、通知の表示を担当します。上記のセクションでは、worker.jsファイルにプッシュ通知のJSONペイロードを送信したため、このファイルはペイロードを「キャッチ」して通知を表示する必要があります。ファイルを開き、showNotificationを呼び出すスクリプトを追加します。

 self.addEventListener('push', ev => { const data = ev.data.json(); var options = { body: data.body, icon: data.icon, data: {url: data.url}, actions: [{action: 'open_url', title: 'Read more'}] }; if(data.vibrate) options.vibrate = [200, 100, 200, 100, 200, 100, 200]; self.registration.showNotification(data.title, options);});self.addEventListener('notificationclick', function(event) { switch(event.action){ case 'open_url': if(event.notification.data.url !== '') clients.openWindow(event.notification.data.url); break; }}, false);

ここでは、から送信されたペイロードを消費しています インクルード Webプッシュと通知の表示。 URLが渡された場合、通知にはアドレスを開くためのボタンが表示され、コンテンツアイテムで[はい]チェックボックスがオンになっている場合はモバイルデバイスが振動します。

これで、通知をテストできます。サイトにアクセスし、通知を購読します。 Kontentで、プッシュ通知コンテンツタイプを使用して新しいアイテムを作成し、公開します。 Webhookが起動すると、通知が表示されます。

Kentico Kontent

それらをプッシュしますが、あまり頻繁ではありません

この記事では、最初から最後までプッシュ通知を実装しました。コンテンツタイプを作成し、Webhookを構成し、Expressアプリケーションでデータを受信し、プッシュ通知としてブロードキャストしました。編集者は、ウェブサイトの訪問者に最新のニュースを簡単に通知できるようになり、数回クリックするだけで済みます。ただし、訪問者が注意を払うように、これらの通知は散発的に適切なコンテキスト内でのみ送信する必要があることに注意してください。

Expressアプリケーションの完全に実装されたコードはここで確認できます。

Headless CMSの導入をお考えでしょうか?

クラウドとマルチデバイスに最適化されたKentico Kontentをお試しください