FirebaseベースとSendGridでメッセージの追跡をする

記事
IT・テクノロジー

FirebaseベースとSendGridでメッセージの追跡をする

前回の記事では、FirebaseとSendGridを利用して、メッセージの追跡情報をWebHookで取り込む方法について解説しました。設定にもよりますが、メッセージの送信の完了や、メッセージの開封、メッセージ中のリンクのクリックなどの追跡情報を、SendGridのサーバーに設定したURLまで送信させることが可能です。その情報をFirebaseのバックエンドサービス(ファンクション/functions)で収集して、Firebaseのデータベースに入れることでメッセージの追跡を実現できます。
前回の記事で触れていますが、メッセージの追跡を行うためにはメッセージの追跡情報と送付するメッセージを紐づける必要があります。この記事ではその詳細を解説します。

SendGridのWebHookで送られてくる情報は「イベント」によって違う

実は、メッセージの追跡情報の中身はイベントによって異なっています。
E-Mailアドレスや、イベントが発生した日時などは共通ですが、微妙に違います。このため、SQLなどのデータベースにこのイベント情報を記録するのは少々面倒です。イベントによって、送られてくる情報が違うので、ほとんどの場合イベントごとにテーブルを分けるなどの処理が必要になります。
Firebaseのデータベースの場合、個々のドキュメントのデータの中身は違っていても、同じコレクションに入れることができるので扱いがシンプルになります。
この中で、共通して使用できるのが、受け取り側のE-Mailアドレス、イベントのタイプ、イベントの時刻などです。
メッセージと結びつける情報は、通常のメッセージ送信の場合が「sg_message_id」になります。マーケティングキャンペーンの場合は「marketing_campain_id」を利用できます。
通常メッセージの場合
通常メッセージの場合は、追跡情報の「sg_message_id」を使います。
t3o0iSleRSikYQnXER7JIw.filterdrecv-p3iad2-745ddd55b7-92qfj-19-5FAB15D1-9.0
このような、ハッシュ化されたIDが追跡情報に含まれています。 これに対して、メッセージを送信する際に、SendGridがレスポンスで返してくるIDは以下の様になっています。
t3o0iSleRSikYQnXER7JIw
完全に同じIDではありませんが、追跡情報の先頭部分が同じになっています。SendGridがメッセージの処理の過程でIDに情報を追加しているためで、最初の部分が一致した場合に、送信したメッセージと追跡情報を結びつけることができます。
このIDは、メッセージ送信リクエストの応答のヘッダに含まれています。応答の「body」ではないので注意が必要です。
axiosなどのモジュールを使って、SendGridにリクエストを送信する場合は、
axios(options).then((res: AxiosResponse) => {
    const sg_message_id: string | string[] | undefined = res.header["x-message-id"];
    if (!sg_message_id && res.data.errors) {
        resolve(undefined);
    } else if (!sg_message_id && !res.data.errors) {
        resolve(undefined);
    } else {
        resolve(sg_message_id as string);
    }
}).catch((error: any) => {
    resolve(undefined);
});
のようにヘッダーの中から、「x-message-id」のタグが付いているデータを取得して記録に残します。
このIDはメッセージ送信後は取得できないので、送信時に取得して記録しておく必要があります。
マーケティングキャンペーンメッセージの場合
マーケティングキャンペーンメッセージの場合は、SendGridに記録が残るので送信時に取得して記録に残す必要はありません。
日本の構造計画研究所経由でSendGridを利用する場合は、「Legacy Marketing Campagins」を利用することになりますので、「GET Retrieve all Campaings」のAPIを使って、キャンペーンのリストを取得すれば、キャンペーンメッセージのIDを取得できます。
ここで取得したIDと、追跡情報の「marketing_campain_id」を使って、メッセージを特定します。

取得したデータはFirebaseのデータベースに保存!

通常メッセージ送信時に取得するメッセージのIDは、フロントエンドに応答として返せば、フロントエンドからデータベースに記録することは可能です。 しかし、WebHookのデータの場合は全て、サーバーで処理する必要があるので、バックエンドからFirebaseのデータベースに直接保存した方が簡単です。

バックエンドから、Firebaseのデータベースにデータを保存するには?

バックエンド(サーバー側)での処理で、Firebaseのデータベース(Cloud Firestore)にアクセスする場合は、Firebase Admin SDKを利用する必要があります。
いずれにしても、バックエンドの実装の際に、Firebase Admin SDK (firebase-admin)のモジュールが必要になるので特別な設定は必要ありません。 あとは、FirebaseのサービスアカウントのAPIキー(secret key)を取得して、Firebase Admin SDKの初期化を行っておけば、フロントエンドからアクセスするのとほぼ同じようなコードでアクセス可能です。
import firebase from "firebase-admin";
.........
const firebase: firebase.app.App = firebase.initializeApp({
    credential: firebase.credential.cert(
      path.join(__dirname,"../serviceAccountKey.json")
    ),
    databaseURL: "https://xxxx-xxxxx-xxxx.firebaseio.com",
  });
のように、APIキーを含んだファイルの指定と、Firebase Cloud FirestoreのデータベースのURLを入れて初期化します。
firebase.firestore().collection("messages").add({
    id: messageId,
    subject: subject,
    message: message,
    email: email
})
のような感じでコードを書けば、IDとメッセージの控えをFirebase Cloud Firestoreに残すことができます。フロントエンドとほぼ同じコードでバックエンドでもデータベースにアクセスできると、コードの移動も簡単にできます!

簡単なメッセージアプリ

これまで紹介してきた機能を組み合わせると簡単なメッセージ送信アプリをつくれます。
簡単なメッセージ入力フォームを作って、メッセージを作成して、バックエンドからSendGridを経由して送信するというシンプルなものです。
これに、メッセージの控えを残す機能と、メッセージの追跡情報を取得する機能を付ければ、送信したメッセージが無事に届いたか、開封されたかなどを追跡できるため、一般のメールシステムより高機能な配信システムが簡単に実現できます。メールを受け取る部分の実装が課題ですが、メッセージの追跡だけでも利用する価値があるアプリです。

まとめ

前回に続いて、FirebaseとSendGridを組み合わせて送信したメッセージを追跡するための実装について解説してきました。今日は、メッセージを特定する方を中心に解説しました。
マーケティングキャンペーンのメッセージはシンプルですが、通常のメッセージの場合、送信時にメッセージのIDを取得して保存しておくのがポイントです。
Firebaseはバックエンドだけではなく、データベース機能も利用できるのでこうした実装には向いていると思います。

サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す