0
0

More than 1 year has passed since last update.

AppsFlyer Push APIからのJSONデータを、Cloud Functionsで受け取り、Cloud Firestoreに流し込むまで

Posted at

自己紹介

AppsFlyerというモバイル広告計測ツールの会社のソリューションアーキテクトです。前職ではIBMでデータエンジニアをやっており、DWHの構築などをネットワークやOSレベルのインフラレベルのこともやっていましたが、基本的にはオンプレだけでしたので、Google CloudやAWSのことをキャチアップしたいと考えているところです。

参考: AppsFlyerとそのアトリビューションの仕組み

AppsFlyerは計測ツールですので、そのローデータをお客様側に持ち出していただいて保管・分析いただくことは通常のユースケースになります。その連携方式の一つがPush APIという機能で、AppsFlyerから発生したイベントをリアルタイムで指定のエンドポイントにデータを送信できるというものなのです。

ただ、対面のお客様はエンジニアではなくマーケターの方だったりしますので「エンドポイントってそもそも何?」というような質問を多々受けることもあります。

「Google CloudやAWSならきっと簡単に作れるんだろうなあ」と思いつつ、自分ではまだ作ったことはなかったので、今回Push APIからの情報をGoogle Cloud側で受け取り、格納する処理を調べながら試しに実装してみることにしました。

Push APIのエンドポイントの仕様

Push APIのサーバー要件を確認すると、成功時にステータスコード200を返すことのできるGoogle Cloud外からアクセス可能なエンドポイントが準備できれば良さそうです。

Screenshot 2022-12-24 at 14.01.41.png

※本番で使うのなら、IPアドレスのホワイトリスト化や、余分なポートを閉じておくようなセキュリティ上の配慮も必要そうですが、今回はこの部分は端折ることにします。

Cloud Functionsでエンドポイントを作る

調べてみたところ、Cloud FunctionsがHTTPリクエストを受け取って簡単に処理できそうなので、これで実装します。

手始めに、認証なしのHTTPSトリガーのCloud Functionsを作成します。

image.png

image.png

このNode.jsのコードを書き換えて、ステータスコード200とRequest body内のJSONをテキスト化して返すようにしました。

const functions = require('@google-cloud/functions-framework');

functions.http('helloHttp', (req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/html"
  });
  const responseMessage = JSON.stringify(req.body);
    
  res.end(responseMessage);
  console.log(responseMessage);
});

これをデプロイすると数分後に、Cloud Functionsが立ち上がり、エンドポイントとのURLも確認できます。
image.png

試しにcurlコマンドを叩いてみると、

curl -X POST https://function-1-qabhtikgmq-an.a.run.app  -H "Content-Type: application/json" -d '{"Id": 123456, "name": "Makoto"}'    

問題なくRequest BodyのJSONがそのまま返ってきました。

{"Id":123456,"name":"Makoto"}  

Cloud Functionsの画面上のログの方からも確認できます。
Screenshot 2022-12-24 at 14.57.21.png

AppsFlyerからテスト送信してみる

AppsFlyerの管理画面「APIアクセス」からPush APIのエンドポイントを設定し、POSTでテスト送信してみると、「テストが正常の送信されました」とのメッセージ。
image.png

Cloud Functionsのログ見ると、データがRequest BodyのJSONとして確かに受け取れていそうです。
Screenshot 2022-12-24 at 15.00.04.png

ちなみにGETでのテスト送信も試したところ、データはURLのパラメータとして送られてきました。
Screenshot 2022-12-24 at 15.01.51.png

ここまでで、Cloud FunctionsにてHTTPリクエストを受け取るためのエンドポイントを作り、実際にテスト送信でデータを受け取れることを確認しました。

Cloud Functionsで受け取ったデータをFirestoreに保存する

せっかくJSON形式でデータを受け取っているので、そのまま格納したいので、適当なNoSQLデータベースサービスがないかを探したところ、Cloud Firestoreが良さそうだとわかりました。

Cloud Firestore には、異なるユースケース向けに最適化された 2 つのモード(Datastore モードとネイティブモード)がありますが、今回はネイティブモードを選択しました。

Cloud Functionsから利用するには、@google-cloud/firestore のパッケージを利用するようですので、package.jsonにこの依存関係を追加します。

package.json
{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0",
    "@google-cloud/firestore": "^6.0.0"
  }
}

また、同じプロジェクト内でCloud Firestore を有効化していれば、あまり細かい接続情報などを意識せずに、Firestoreとの接続ができるようです。
あとは任意のコレクションIDとドキュメント名を指定し、JSONデータを入れていけば良さそう。

今回は受け取ったRequest bodyをそのまま新規のドキュメントとして作っていきたいので、ドキュメントのIDを自動付与するfirestore.collection('af_push_api_data').add(req.body);でデータを格納することにしました。

index.js
const functions = require('@google-cloud/functions-framework');
const {Firestore} = require('@google-cloud/firestore');

// Create a new client
const firestore = new Firestore();

functions.http('helloHttp', (req, res) => {
  // Add a new document with a generated ID
  firestore.collection('af_push_api_data').add(req.body); 
  
  res.sendStatus(200);
});

上記のコードをデプロイし、AppsFlyer側からテスト送信したところ、Firestoreに無事にドキュメントが作られて、フィールドも入ってます。

image.png

クエリビルダーで簡単にデータもみれますね。
Push APIでのデータ送信はリアルタイムに各種のイベントもどんどん連携されてくるので、面白いです。

image.png

まとめ

一部コーディングのデバッグなどでは苦労しましたが、環境構築はほとんど不要で、簡単にできてしまうのがクラウドのすごいところだと実感しました。Google Cloudはもっと触って理解していきたいです。

本番利用では、さらにCloud Load Balancingなどで受けるようにして、セキュリティ面での対応も入れると良さそうですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0