🤖

DevCycle で MAU が2重カウントされていた件について

2024/10/22に公開

はじめに

こんにちは、yoshi です。
今回はフィーチャーフラッグプラットフォームを提供している DevCycle を使用していて、期待する MAU 数と実測値で乖離があったため、調査し解決した方法について共有します。

対象読者

  • DevCycle の Client SDK を利用している開発者

説明しないこと

MAU が2重カウントされている

私たちのチームでは、普段 DevCycle を使用して Feature Flag の制御を行っています。
しかし、DevCycle のダッシュボードで確認したところ、想定していた MAU 数と実測値で乖離があることに気づきました。
実際に DevCycle へのリクエストを検証ツールで確認すると、DevCycle の Configuration に関するリクエストが 2 回行われていました。

リクエストの payload を見ると、1 回目は匿名ユーザーで、2 回目は認証済みユーザーでリクエストが行われていることがわかりました。

1回目
isAnonymous: true
sdkType: client
sdkVersion: 1.29.1
sdkPlatform: react
2回目
isAnonymous: false
sdkType: client
sdkVersion: 1.29.1
sdkPlatform: react

原因

ではなぜ リクエスト 2 回が行われていたかというと、SDK の初期化が 2 回行われていたためでした。
私たちのプロダクトでは、Web フロントエンドでの SDK として React SDK を使用しています。

React SDK に関するドキュメントでは、Get Started のセクションに以下のように記載されていました。

If you do not pass in a user to the provider, it will create an anonymous user and initialize the SDK with it. You can then call the identifyUser method on the client once the user has been authenticated. See Identifying Users & Setting Properties for more details.

つまり、DevCycle の SDK を初期化する際に User ID を渡さない場合は、匿名ユーザーが作成されて SDK が初期化されます。
その後ユーザーが認証された(User ID がセットされた)時、identifyUser メソッドを呼び出してユーザーを識別されていました。
私たちのプロダクトでは認証済みのユーザーのみ利用可能なため、匿名ユーザーが無駄に作成されていることが原因で 2 重カウントしていたというわけです。
コードで表すと以下のようになります。

import {
  useIsDevCycleInitialized,
  withDevCycleProvider,
  useDevCycleClient,
} from '@devcycle/react-client-sdk';

let identified = false;
function App() {
  const devcycleClient = useDevCycleClient();
  // ユーザーデータを取得
  const { data: user, isFetched } = useUserFromMyUserStorage();
  if (user && !identified) {
    devcycleClient.identifyUser({
      user_id: user.id,
    });
    identified = true;
  }

  return <div>App</div>;
}

export default withDevCycleProvider({
  sdkKey: '<DEVCYCLE_CLIENT_SDK_KEY>',
})(App);

解決方法

Deferred Initialization のオプションを使用します。
これで、ユーザーデータの取得完了し identifyUser メソッドが呼ばれるまで SDK の初期化を遅延させ、 DevCycle の Configuration のフェッチが行われないようにすることができます。
このオプションを使用した結果、 DevCycle の Configuration に関するリクエストが 1 回になりました。

import {
  useIsDevCycleInitialized,
  withDevCycleProvider,
  useDevCycleClient,
} from '@devcycle/react-client-sdk';

let identified = false;
function App() {
  const devcycleClient = useDevCycleClient();
  // ユーザーデータを取得
  const { data: user, isFetched } = useUserFromMyUserStorage();
  if (user && !identified) {
    devcycleClient.identifyUser({
      user_id: user.id,
    });
    identified = true;
  }

  return <div>App</div>;
}

export default withDevCycleProvider({
  sdkKey: '<DEVCYCLE_CLIENT_SDK_KEY>',
+ options: { deferInitialization: true },
})(App);

まとめ

認証を必須としたプロダクトにおいては、deferInitialization のオプションを使用することで、匿名ユーザーが作成されるのを防ぐことができました。
今回のようなユースケースに対しての解決方法は公式ドキュメントに記載があったため、最初に公式ドキュメントをしっかり読んでおくべきでした...。
また、並行して MAU の乖離の件について DevCycle のサポートチームに問い合わせを行い、スムーズに対応いただきました。
大変感謝しています。

最後に

AI Shiftではエンジニアの採用に力を入れています!
少しでも興味を持っていただけましたら、カジュアル面談でお話しませんか?
(オンライン・19時以降の面談も可能です!)
【面談フォームはこちら】
https://hrmos.co/pages/cyberagent-group/jobs/1826557091831955459

AI Shift Tech Blog

Discussion