【書き起こし】メルペイのキャンペーンの舞台裏 〜Growthを支える仕組み〜 – 小川 芳樹【Merpay Tech Fest 2021】

Merpay Tech Fest 2021は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知れるお祭りで、2021年7月26日(月)からの5日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。

この記事は、「メルペイのキャンペーンの舞台裏~Growthを支える仕組み~」の書き起こしです。

小川芳樹氏:それでは、始めさせていただきたいと思います。「メルペイのキャンペーンの舞台裏~Growthを支える仕組み~」と題して発表させていただきます。

発表いたしますのは、株式会社メルペイ Product Engineering Division CD&UX Growthチーム小川です。2018年12月にバックエンドエンジニアとしてメルペイに入社し、Growthチームおよびメルペイクーポンマイクロサービスのテックリードを担当しております。よろしくお願いいたします。

こちらが本日の発表内容になります。メルペイGrowthチームについての紹介、開発している各マイクロサービスの紹介、その運用上の仕組みについての紹介といったものを中心に発表させていただきたいと思っております。

メルペイGrowthチームについて

まず初めに、メルペイGrowthチームについてご紹介していきたいと思います。

今年の4月にメルペイは、利用者数1,000万人を突破したことを発表させていただきました。もちろん、これまでメルカリを使っていただいていた方もいらっしゃるとは思いますが、CMやキャンペーンによって知っていただいた方も多くいらっしゃるのではないでしょうか。

メルペイでは、より多くのお客さまにメルペイをご利用していただくために、さまざまなキャンペーンを行ってきました。メルペイのご利用に応じてポイント還元をするキャンペーン、メルペイの加盟店でご利用いただけるクーポンの配信、友達へメルペイを紹介していただくことでポイントをもらえるキャンペーン。また、マイナポイントをメルペイで申し込みいただいた方にお得にメルカリを利用していただけるキャンペーンなどなど、ここに挙げているものは一例にすぎないのですが、このようなキャンペーンをマーケティングチームと共に開発・運用を行っているのがメルペイGrowthチームになります。

これらのキャンペーンは、複数のマイクロサービスを組み合わせて実現しています。メルペイクーポンの配信を担当する Coupon Service、ポイント還元を担当する Santa Service、マイナポイントの申し込みを管理する MynumPoint Service、キャンペーンの運用管理を行う Opzilla というツールなどがあって、そのほかメルペイを構成するマイクロサービス群と連携してキャンペーンを実現しています。

Coupon Service について

まずは、クーポンのマイクロサービスから紹介していきたいと思います。

まず、メルペイクーポンとはどういうものかというところから紹介していきたいと思います。メルペイクーポンは、メルペイの加盟店でお得に商品を購入することができるサービスになっています。クーポン画面を提示することでお得になる「見せるクーポン」や、お支払い額に応じてポイント還元を受けられる「ポイントバッククーポン」といったものを提供しています。サービスイン当初には、セブンイレブンのおにぎりが11円で買えるクーポンを配布するなど、話題性のあるクーポンを継続的に提供しています。

メルペイクーポンは、画面の改修や加盟店さまからの要望を容易に実現するために一部の画面でWebViewを採用しています。そのため、 Coupon Service としては、フロントエンドを担当するマイクロサービスと、バックエンドを担当するマイクロサービスから構成されています。詳細については割愛しますが、ネイティブアプリからのリクエストも、WebViewからのリクエストも、merpay-apiというAPIレイヤーを通じて共通のバックエンドにリクエストされます。クーポン情報に加えて、iD(アイディ)の設定有無やメルペイ残高の情報などをアグリゲーションしてクライアントに返すという構成になっております。

メルペイクーポンサービスの主要な機能として、1人1回限りのクーポンをお客さまごとのクーポンの使用状態を管理する機能。あと、メルカリ起動時などに新着のクーポンや利用期限間近のクーポンをお知らせする機能といったものがあります。

また、お客さまがメルカリの配送先住所として設定している都道府県に応じて適切にクーポンを出し分けたり、特定のお客さまに向けたクーポンの配信機能。そして、こちらは後述しますが、 Santa Service と連携したポイントバッククーポンなどの機能があります。

Santa Service について

次に、 Santa Service について紹介していきたいと思います。 Santa Service は、技術的に特徴的な要素が多いので詳しく説明していきたいと思います。

Santa Service は、メルペイのキャンペーンにおけるポイント還元などのインセンティブ付与を行うためのマイクロサービスになっています。お客さまの何らかのアクションをトリガーにしてインセンティブを付与するということがメインの機能になります。例えば、メルペイを使った購入をトリガーにポイントを付与する。本人確認をトリガーにポイントを付与する。また、定額払いの精算をトリガーにポイントを付与するといったものがあります。

Santa Service の技術的な特徴を紹介していきたいと思います。まず、 Santa Service 内のほぼすべての処理は PubSub driven で実行され、すべてのインセンティブ付与は非同期で処理されます。のちほど詳しく説明しますが、インセンティブ付与処理でエラーが発生しても、決済系などのほかの重要なマイクロサービスへ影響を与えないような構成となっています。またPubSubの性質上、意図せず何度もインセンティブ付与が行われることのないよう冪等(べきとう)性を担保した処理フローになっています。また、エラーが発生した際にも自動でリトライされるような機構になっています。こちらものちほど紹介しますが、インセンティブ付与の条件判定に利用するお客さまの情報、例えば年齢や本人確認済みかどうかといった情報に関しては、都度、該当の情報を管理するマイクロサービスに最新の情報を問い合わせるという構成になっています。一部、過去のキャンペーンの参加履歴やエントリーが必要なキャンペーンであれば、そのエントリーの情報などの事前抽出が可能な変動性のない情報だったり、 Santa Service 自身が保持する情報に関しては自身のデータベース上に保存しておいて、それを用いるという場合もあります。

それでは、 Santa Service がどのような処理を行ってキャンペーン条件の判定を行い、インセンティブを付与しているかという流れについて具体的に掘り下げていきたいと思います。処理の流れとしては、大きく5つのコンポーネントに分別することができます。

まずは、お客さまのアクションをもとにPubSubメッセージをパブリッシュする、外部マイクロサービスの PubSub Publisher があります。関係するマイクロサービス内にそれぞれ Publisher が実装されています。例えば決済に関するアクションであれば、ペイメントサービスに Publisher が実装されており、そのすべてのアクションについてメッセージがパブリッシュされています。

次に、 Santa Service 内に実装されている 1st Subscriber です。先ほどの外部マイクロサービスからのメッセージをサブスクライブする役割になります。外部マイクロサービスからパブリッシュされるPubSubのメッセージは、そのサービスのドメインのデータとして送られてきますので、インセンティブ付与の処理に関係ないメッセージも一部含まれています。例えば決済を例に挙げて説明すると、1つの決済情報においてもオーソリやキャプチャ、もしくはキャンセルといった複数の状態を遷移することになります。その都度ペイメントサービスからメッセージはパブリッシュされてきますので、その中の Santa Service で利用する処理に必要なステータスのメッセージだけ取り出して、必要ないメッセージはそこで捨ててしまう。必要のあるメッセージだけを Santa Service で扱う、 Santa Service のドメインのデータに変換したPubSubメッセージを次の 2nd Subscriber というところに、これも PubSub を用いてパブリッシュするという役目になっています。

次に、 2nd Subscriber になります。 2nd Subscriber では、先ほど説明した 1st Subscriber からパブリッシュされたメッセージをサブスクライブします。そのメッセージをもとに、キャンペーンごとに設定されたキャンペーン条件について判定して、その条件にマッチした場合にポイント額を、お客さまにどれぐらいのポイントを付与するかというのを計算して、インセンティブ付与のリクエストを外部のマイクロサービスに行うといった役割になります。こちらの処理の詳細については、のちほど改めて紹介したいと思います。

そして、先ほど述べたキャンペーン条件のチェックに必要な情報を保持するマイクロサービス群や、実際のインセンティブを付与したり、プッシュ通知を行うマイクロサービスがあり、これらは Santa Service からgRPCでAPIリクエストを行っております。

ここで、なぜ1つの Subscriber で処理しないで、ファースト、セカンドの Subscriber の多段構成になっているのかというところを疑問に思われる方も多いと思っています。一番大きな理由としては、キャンペーン条件の判定が複数のマイクロサービスに依存しているということが挙げられます。複数のマイクロサービスに依存するということは、依存したマイクロサービスに障害が発生した場合に影響を受ける確率が高いということになります。 Santa Service 内では、エラー発生時にPubSubのメッセージを再度処理するというリトライ機能が実装されているんですが、瞬間的なネットワークエラーといったものであれば、このリトライ機能で解決することができます。ただ、システム的に長期的な障害が発生した場合などに無限にリトライを繰り返してしまうと、処理していない、処理できないメッセージがどんどん滞留していってしまい、 Santa Service 自体のパフォーマンスにも大きな影響を与えてしまうことになります。こういったパフォーマンスの低下を避けるために、 Santa Service ではリトライ自体は5回までにして、それを超えたエラーとなったメッセージに関しては、 Santa Service 内のデータベースに保存されるようになっております。

Santa Service のデータベースに保存された 2nd Subscriber へのメッセージというのは、 Self-healing というBatch機能があり、これを実行すると任意のタイミングで再度 2nd Subscriber にパブリッシュすることが可能になっています。外部マイクロサービスからパブリッシュされるメッセージをサブスクライブしているマイクロサービスというのは、 Santa Service 以外にもたくさん存在していますので、 Santa Service 内でエラーが起きたという都合だけで再度同一のPubSubメッセージを外部のマイクロサービスからパブリッシュしてもらうということはなかなか難しいことだと思っています。そこで一段、外部向けと内部向けという構成をつくったうえで一段返すことで、任意のタイミングで再度同一のメッセージを Santa Service 内でパブリッシュするということができるようになっています。以上が、 1st Subscriber と 2nd Subscriber に分けられている理由になっております。それでは次に、 2nd Subscriber の具体的な処理について紹介していきたいと思います。

2nd Subscriber 内で処理されるキャンペーンのマスターデータというのは、こういった情報から構成されています。キャンペーンのIDだったり、キャンペーンの名称、経理処理するためのアカウンティングコード、キャンペーン自体の開始終了時刻、割合還元か固定額還元かとその値、還元条件を表すフィルタリング条件、ポイント付与のタイミング、1度の決済に対する還元額上限、キャンペーン期間内の還元額上限などの情報から構成されています。複数のキャンペーンが同時に開催されていますので、有効なキャンペーン期間のものすべてに対して条件判定を行い、インセンティブ付与の処理を行っていきます。ここで、太字で示したフィルタリング条件というものについて改めて詳しく説明していきます。

フィルタリングとは、キャンペーンごとにフレキシブルに条件設定を行うための機能になっています。フィルタリングの設定はキャンペーンデータにJSON形式で保存することで、あらかじめ実装されたフィルタを任意の組み合わせで設定することができます。例えば先述したポイントバッククーポンの場合には、200円以上の決済であるかどうか、特定の加盟店での決済であるかどうか、クーポンを使用済みであるかどうかというのがフィルタリング条件として設定されます。

先ほどのフィルタリング条件は、データベース上ではこのようにJSONでシリアライズして表現されて、キャンペーンデータのマスターデータとして保存されています。

ここで、先述したポイントバッククーポンにおける Santa Service と Coupon Service の連携を例に、具体的にどのような処理が行われているかというのを説明したいと思います。ポイントバッククーポンは、クーポン画面の「クーポンを使う」という操作を行ったあとに、指定の加盟店で指定額以上の決済をすることでポイント還元をするものになります。この図で説明しますと、お客さまがメルペイで決済を行ったものがトリガーとなって、 Santa Service にそのメッセージが送られます。そのメッセージの内容を見て条件を満たした決済かどうかというのを確認します。例えば101円以上かどうか。また、指定の店舗で決済されているかどうかというのを確認して、これが満たされなかった場合はここで処理は終わりになります。満たした決済であれば Coupon Service に問い合わせたうえで対象となるクーポンを使っているかどうかについて問い合わせます。これも使っていると判断された場合は、 Santa Service 内でポイントバックの処理が行われることになります。以上が、 Santa Service 内で行われているシステム的な説明になります。

キャンペーン運用を支える仕組み

次に、キャンペーンの運用を支えるための仕組みについて紹介していきたいと思います。

これまで述べてきたように、多くのキャンペーンを実施しているほか、クーポンについては多くの加盟店さまのクーポンを掲載させていただいているため、同時に管理しなければいけない数も多くなってきます。そのためスケーラビリティーのある運用体制やフローが重要となってきます。特に、特定の作業者がボトルネックとならないようなシステムのつくりとなっていることが重要になってきます。キャンペーンデータやクーポンデータのみであれば基本的にはエンジニア不要で、データ作成とQA、本番反映まで行えるようなシステムとしています。

具体的には、クーポンデータやキャンペーンデータに関しては GitHub のリポジトリ上で管理することとしています。データはyamlファイルで保存され、yamlの中のキーは、データベース上のカラムと1対1対応するようになっています。そのデータが保存されているリポジトリに、CircleCIや GitHub Action を用いてデータのバリデーションやリリースの自動化が設定されています。例えば購入額に対する割合での還元のキャンペーンにおいて、その還元の値が100%を超えているようなデータを間違えて作成されていた場合には、それはCIによってエラーとなってマージできないようになっています。また、本番環境へのデータの反映についても、メインブランチにマージしたあとに、 Spanner へのデータマイグレーションスクリプトによって行われるようになっています。また、 GitHub を用いている理由としては、リリース差分を確認しやすいことや、軽微な修正であれば GitHub のGUI上から行えることも大きなメリットであると考えております。

とはいえ、いきなりyamlファイルを記述するということは、エンジニアであっても大変だと思います。また、システムで利用するデータベース上のカラムは、人間にとっては冗長だったりシステムの使用を理解している必要もあります。そこで、データの作成についてはGoogleスプレッドシート上にテンプレートに沿ったデータを作成し、 Google Apps Script を用いてyamlファイルに変換するようなシステムを組んでいます。これによりプロダクトメンバーだけでなく、マーケティングチームやセールスチームがキャンペーンデータを作成することも可能になっています。

また、クーポンデータの作成においては、幾つかの画像の作成が必要となってきます。当初はデザイナーの方に一つ一つ作成していただいたのですが、ある程度テンプレートとして型が固まってきた段階で画像の作成を機械化するようにしました。この作成のインターフェースとしては、Slackのbotを用いていますので、こちらも作業は誰でも簡単に行えるようになっています。

また、クーポンの実施に際しては、どのようにクーポンが表示されているかというのを加盟店さまに共有する必要があります。こちらも以前は、開発環境にクーポンデータを反映したうえでスクリーンショットを1つずつ実機で取っていくという必要があったんですが、こちらについてもDockerコンテナ上に必要最小限のサービスを立ち上げて、クーポン画面を emulate したものを Puppeteer を使ってスクリーンキャプチャを行うようなシステムを構築しています。こちらも Slack bot から実行できるようになっています。この詳細については、メルカリエンジニアリングブログに記事がありますので、興味のある方はご覧になってみてください。

先ほどから述べておりますように、複数のキャンペーンやクーポンが並列開催されていますので、現在開催中のものを一覧で表示したくなることがあります。特にクーポンは、お客さまごとに表示されているクーポンが異なる場合がありますので把握することが難しくなってきます。そのようなニーズのため、開催中のキャンペーンデータやクーポンを一覧表示できるツールとして、 Opzilla というものを運用しています。このように一覧で表示することができます。ただ、本番のデータを扱うため、 Google OAuth による閲覧権限管理機能も実装しています。これらのツールやシステムを組み合わせてメルペイのキャンペーンやクーポン実施についてスケーラビリティーを持って実施しております。

今後の展望&まとめ

最後に、今後の展望とまとめになります。

メルペイのプロダクトはお店でのお支払いのみならず、メルペイスマート払いやメルコインといった、さまざまな領域に進化していっています。その各機能の魅力をお客さまに届けるための Growth Platform としての役割をこれまで紹介してきた Coupon Service や Santa Service などを中心にGrowthチーマーになっていき、柔軟かつスピーディーにキャンペーンが実施可能な基盤づくりを進めていこうとしています。

最後になりますが、まとめとなります。メルペイのGrowthに関わるマイクロサービスの詳細や技術的な特徴について紹介してきました。また、スケーラビリティーのあるキャンペーン運用のための工夫について紹介してきました。最後に、Growthチームは、メルペイのさまざまなプロダクトに幅広く関わることができる おもしろいポジションだと個人的には思っております。メルペイでは、ミッション、バリューに共感できるエンジニアを募集しています。きょうの発表を聞いて興味を持たれた方は、ぜひメルペイの採用ページから応募していただけるとうれしいと思います。

それでは、発表は以上となります。ご清聴ありがとうございました。