Mixpanelは、画面遷移ではなく「ユーザーが何をしたか」をイベント単位で記録し、ファネル・リテンション・コホートとして読み解くプロダクト分析基盤です。SQLを書かずに分析できる点が紹介されがちですが、実装側で効いてくるのはその手前にあります。どのIDでユーザーを束ねるか、どこまでを自動計測に任せるか、月あたりのイベント数がいくつになるか。
この記事では、JavaScript SDKの初期化、サーバー側からのIngestion API送信、ID統合方式の選択、データレジデンシーとBigQueryエクスポート、イベント従量課金の構造までを、そのまま動かせる粒度で整理します。数値と仕様は参照時点(2026年9月)の公式ドキュメント記載に基づきます。
まとめ:Mixpanel導入で先に決めるID統合方式とイベント課金の勘所
- 記録の単位はイベント:イベント名とプロパティの組を送り、
distinct_idで人に紐づける。画面単位の指標は後から作る。 - ブラウザ用パッケージは
mixpanel-browser:サーバー用のmixpanelとは別物。ライセンスはApache-2.0。 - 自動計測は既定でオフ:
autocaptureは初期値がfalse。オンにするとクリック・スクロール・入力まで拾い、イベント数が一気に増える。 - ID統合方式は後から変えられない:データが入ったプロジェクトではSimplifiedとOriginalを切り替えられない。最初の選択がそのまま残る。
- 重複排除は送信側の責任:
$insert_idを付けないと、リトライがそのまま二重計上になる。 - 費用はイベント数に連動:無料枠は月100万イベント。Growthは月2,000万イベントまでで、うち最初の100万は無料。
Mixpanelの計測モデルとGA4との構造差が実装に効く場面
Mixpanelに送るデータは、大きくイベントとユーザープロフィールの2系統に分かれます。設計の入口はこの分界点です。
イベント・ユーザープロパティ・distinct_idの3要素の関係
イベントは「いつ・誰が・何をしたか」の記録で、event(イベント名)と properties(付随情報のJSON)で構成されます。公式のTrack Eventsリファレンスでは、この2つが必須項目として定義されており、properties の中に token・time・distinct_id・$insert_id を入れる形です。
ユーザープロフィールは、同じ人に紐づく現在の属性を保持します。JavaScript SDKでは mixpanel.people.set() で更新し、プランやロールのような「その時点の状態」を持たせます。イベント側のプロパティは送信時点の値で固定される一方、プロフィールは上書きされるため、後から集計軸に使いたい属性はイベント側にも載せておくのが安全です。
GA4と並行運用したときに数字が合わない原因になるID設計の差
MixpanelとGA4を同じサイトに入れると、ユーザー数はほぼ確実にずれます。原因は計測漏れではなく、人の数え方の違いです。MixpanelのIdentity Management Overviewには「The $user_id is always set as the distinct_id for the user」と書かれており、ログイン済みのユーザーIDが常に人の識別子になります。匿名時の $device_id は、後からログインした時点で同じ人へ束ねられる仕組みです。
端末をまたいでも、ログインさえすれば1人として串刺しになる。この挙動が、セッションやブラウザ単位の集計とは合いません。両方を並べて運用するなら、KPIの定義書に「この指標はどちらのツールを正とするか」を先に書いておきます。GA4側の仕組みと運用体制の考え方はGA4とは?仕組みとUAとの違い・導入と運用体制の判断にまとめています。
JavaScript SDKの導入手順とautocapture既定値の確認
フロントエンドの計測は、npmパッケージを入れて初期化するところから始まります。mixpanel-jsのリポジトリが公開しているブラウザ向けの配布名は mixpanel-browser、ライセンスはApache-2.0です。サーバー側で使う mixpanel とは別パッケージなので、Node.jsのバックエンドでは取り違えに注意します。
mixpanel-browserのinitで指定する4つの初期化オプション
JavaScript SDKのドキュメントが示す初期化の形は次のとおりです。トークンは公開されるため、書き込み専用のプロジェクトトークンを使います。
import mixpanel from 'mixpanel-browser';
mixpanel.init('YOUR_PROJECT_TOKEN', {
autocapture: true,
track_pageview: true,
record_sessions_percent: 100,
record_heatmap_data: true,
});
mixpanel.identify('user_10482');
mixpanel.people.set({ plan: 'Premium' });
mixpanel.track('Checkout Completed', {
amount: 12800,
currency: 'JPY',
plan: 'Premium',
});
record_sessions_percent はセッションリプレイの収録率で、100を指定すれば全セッションが対象になります。料金プランにはリプレイ本数の上限があり、本番で100にすると月の半ばで枠を使い切ります。検証環境で100、本番は低い値から始めるのが無難です。
identify の呼び出し位置にも注意が要ります。公式ドキュメントはユーザー登録時とログイン時に呼ぶ形を示しており、この2箇所を外すと匿名IDのまま別人として積み上がります。SPAならルーティングではなく認証状態の変化に紐づけてください。
autocaptureで拾える操作の一覧と既定値がfalseである理由
autocapture の初期値はfalseです。有効にすると、ドキュメントに列挙された次の操作が自動で記録されます。
pageview: "full-url":URL単位のページビューclick・rage_click・dead_click:クリックと、反応が無い箇所の連打input・submit:入力とフォーム送信scroll:スクロールcapture_text_content: false:要素のテキスト本文は既定で取らない
この一覧のうち、イベント数を押し上げるのはスクロールとクリックです。1セッションあたり数十イベントが自動で積まれるため、課金対象のイベント数は自前計測だけの場合の数倍になります。テキスト本文の取得が既定でオフなのは、フォームの入力内容がそのまま送られる事故を避けるため。trueにする判断は個人情報の扱いと合わせます。
最初の導入では autocapture: false のまま、設計したイベントだけを track で送る形をお勧めします。後から足すのは簡単ですが、いったん入ったイベントは消えません。
Ingestion APIによるサーバー側計測と重複排除の実装
決済完了や解約のように、ブラウザで取りこぼすと痛いイベントはサーバー側から送ります。SDKを使わずHTTPで直接叩けるのがIngestion APIです。
track APIの必須プロパティと$insert_idによる重複判定の条件
エンドポイントは POST https://api.mixpanel.com/track。リクエストボディはイベントオブジェクトの配列で、1リクエストにつき最小1個から最大2,000個までを載せられます。Content-Typeは application/json です。
curl -X POST https://api.mixpanel.com/track \
-H 'Content-Type: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @events.json.gz
# events.json の中身(gzip前)
[
{
"event": "Subscription Renewed",
"properties": {
"token": "YOUR_PROJECT_TOKEN",
"distinct_id": "user_10482",
"time": 1789600000,
"$insert_id": "renew-2026-09-user_10482-01",
"plan": "Premium",
"amount": 12800
}
}
]
重複排除の鍵は $insert_id です。リファレンスには「(event, time, distinct_id, $insert_id)が同一のイベントは重複扱い」と定義されており、この4つが揃って初めて同一と判定されます。裏を返すと、リトライのたびに time を現在時刻で入れ直すと別イベントとして通ります。送信キューに積む時点で time と $insert_id を確定させ、リトライでは同じ値をそのまま再送してください。
$insert_id には、注文IDや請求サイクルのように業務側で一意になる値を使うと、後から突合できます。UUIDをその場で生成する実装は、リトライのたびに値が変わるため機能しません。
1リクエスト2000件・1MB上限とレート制限に合わせた送信設計
公式が示すレート制限は「2GB of uncompressed JSON/minute or ~30k events per second」。バッチ処理で過去分を流し込む場合でも、この上限に当たるのは相当な規模です。ただし瞬間的な集中は429を返すため、ドキュメントは指数バックオフの実装を求めています。
送信側の作り込みは3点で足ります。1リクエストは2,000件を超えない。Content-Encoding: gzip を付ける。429を受けたら待機時間を倍にしながら再送し、そのとき $insert_id と time は変えない。
| 項目 | 上限値 | 実装での扱い |
|---|---|---|
| 1リクエストのイベント数 | 2,000件 | キューを分割して送る |
| 1イベントのサイズ | 1MB未満 | 大きいJSONは載せない |
| プロパティ数 | 255個未満 | 命名規則で増殖を抑える |
| ネストの深さ | 3まで | 平坦化して送る |
| レート制限 | 毎分2GB・毎秒約3万件 | 429は指数バックオフ |
移行や初期投入で過去データを入れる場合は、専用のimport系エンドポイントを使う前提で設計します。/track で古い time のイベントを大量に流す作りは、運用が始まってから取り返しがつきません。
Simplified ID Mergeの選択基準と後から変更できない制約
Mixpanelの実装で最も後戻りしにくいのが、ID統合方式の選択です。ここだけは着手前に決めます。
$user_idと$device_idでdistinct_idが決まる判定の流れ
Simplified方式では、イベントに含まれる $user_id と $device_id から識別子が決まります。ログイン前は $device_id が識別子の役割を担い、ログイン後は $user_id が常に distinct_id になる。同じ人が複数端末を使っても、それぞれの $device_id が同じ $user_id へ束ねられます。
この流れを実装に落とすと、やることは2つです。匿名時はSDKが生成した $device_id をそのまま使い、ログイン成功の直後に identify でユーザーIDを渡す。サーバー側から送るイベントには、必ずログイン済みのユーザーIDを distinct_id として入れる。フロントとバックエンドでIDの体系がずれていると、同じ行動が別人として記録されます。
500ID上限のOriginal方式を新規プロジェクトで選ばない判断
Original方式は、$identify・$merge・$create_alias という専用イベントで識別子を結び付けます。ドキュメントには「There is a limit of 500 IDs that can be merged into a single ID cluster」と上限が明記されており、1人に統合できるIDは500個まで。端末やブラウザを頻繁に変える利用者がいるサービスでは、この上限に当たる余地があります。
そして決定的な制約が、切り替えの不可逆性です。「You cannot switch between the two APIs if your project already contains data in it」と書かれているとおり、データが1件でも入ったプロジェクトでは方式を変更できません。作り直すなら新しいプロジェクトを立て、計測をやり直すことになります。
新規に立ち上げるプロジェクトなら、デバイスID数に上限が無いSimplified方式を選ぶ判断で問題ありません。Original方式を選ぶ理由があるとすれば、既存プロジェクトの過去データと同じ方式に揃える場合に限られます。着手前に、この1点だけは合意しておきます。
データレジデンシー設定とBigQueryエクスポートの前提条件
計測が動き出すと、次に問われるのが保存先と持ち出し方です。どちらも後から変えると費用が発生します。
api_hostでEU・インドへ送信先を切り替える設定と注意点
Mixpanelはリージョン別のエンドポイントを持ちます。SDKのドキュメントでは、EUなら api_host に https://api-eu.mixpanel.com、インドなら https://api-in.mixpanel.com を指定する形が示されています。Ingestion API側も同じ規則で、ベースURLの api が api-eu・api-in に置き換わる形です。
ここで見落としやすいのが、プロジェクト側の設定とSDK側の設定を両方合わせる必要がある点です。EUレジデンシーのプロジェクトに対して既定のUSエンドポイントへ送ると、データは届きません。フロントのSDK、サーバーのAPI呼び出し、外部ツール連携の3箇所で送信先を揃えます。
この一覧に日本リージョンは含まれません。国内保管が契約上の前提なら、そこで採用可否が決まります。
mp_master_eventのJSON列からBigQueryで値を取り出す書き方
生データを自社のDWHへ落とすなら、Data Pipelinesを使います。BigQuery連携のドキュメントによれば、これはGrowthまたはEnterpriseの顧客が追加パッケージとして契約する機能で、標準プランには含まれません。エクスポート先は自社が管理するBigQueryデータセットです。
出力されるテーブル構成には癖があります。イベントは mp_master_event という単一テーブルにまとまり、カスタムプロパティはすべてJSON型の properties カラムに格納されます。ユーザープロフィールは mp_people_data_*、ID紐付けは mp_identity_mappings_data_*、エクスポートの監査は mp_nessie_export_log です。
SELECT
JSON_VALUE(properties, '$.plan') AS plan,
COUNT(*) AS events
FROM `my_project.mixpanel_export.mp_master_event`
GROUP BY plan
ORDER BY events DESC
権限は、サービスアカウント [email protected] に対して、プロジェクトレベルでBigQuery Job User、データセットレベルでBigQuery Data Ownerを付与します。ドキュメントは「Mixpanelが生成したテーブルのスキーマを修正しないこと」と明記しており、パーティション設計を変えたい場合は別テーブルやビューを作る方式になります。取り込んだ後の変換層をどう組むかはETLとは?仕組み・ELTとの違い・ツール選定が、DWH側の費用と制約はBigQueryとは:サーバーレスDWHの仕組みと料金が受け持つ役割です。
イベント従量課金の構造と、計測設計でコストが跳ねる典型パターン
Mixpanelの費用はユーザー数ではなくイベント数で決まります。設計の巧拙がそのまま請求額に出る構造です。
無料枠100万イベントとGrowthの2000万件までの費用の考え方
公式の料金ページに記載されている区分は3つ。Freeは月100万イベントまで無料、Growthは月2,000万イベントまでを対象とし、うち最初の100万イベントは無料、Enterpriseは見積もりベースです。ボリュームディスカウントの記載もあり、実額は交渉の余地があります。
| 項目 | Free | Growth |
|---|---|---|
| 月間イベント数 | 100万まで | 2,000万まで |
| 保存レポート | 5件/シート | 無制限 |
| セッションリプレイ | 月10,000 | 月20,000 |
| 機能フラグ | 10個 | 50個 |
検証で押さえるべきは、自社の想定イベント数が100万に収まるかどうかの一点です。月間アクティブ1万人のサービスなら、1人あたり月100イベントで上限に届きます。自前で設計したイベントだけなら収まる規模でも、自動計測を入れた途端に超えます。
スクロール計測と自動計測でイベント数が数倍に膨らむ設定の見直し
費用が跳ねる原因は、ほぼ次の3つに集約されます。
- autocaptureの全項目オン:スクロールとクリックが1セッションで数十件積まれる
- ポーリングや自動更新のイベント化:ユーザーの意思が無い動きを記録している
- デバッグ用イベントの残置:開発中に入れた粒度の細かい計測が本番に残る
削る順番は上から。まず scroll と dead_click を落とし、それでも収まらなければ自動計測そのものをオフにして、設計したイベントだけに戻します。判断のものさしは「そのイベントで意思決定が変わるか」の一点。レポートに一度も出てこないイベント名は、翌月から送るのをやめて構いません。
GA4と併用するかMixpanelへ寄せるかの判断基準と見送り条件
受託開発の現場で問われるのは「入れるべきか」ではなく「どの条件なら回収できるか」です。ここは条件付きで言い切ります。
Mixpanelを採用してよい3条件:プロダクト主導・実装体制・BQ連携
採用が噛み合うのは、次の3条件が揃った案件です。第一に、SaaSやアプリのようにログイン後の行動が価値の中心にあること。$user_id で人を串刺しにできるサービスでなければ、Mixpanelの強みは出ません。第二に、イベント設計を維持できる開発体制があること。計測コードは機能追加のたびに腐るため、仕様変更時に計測も直す運用が要ります。第三に、生データをDWHへ落として他のデータと結合する計画があること。
この3つが揃う案件では、計測設計からSDK実装、BigQueryへのエクスポート、変換層の構築までを一続きで設計したほうが速く進みます。分析基盤側の設計を含めた相談先をお探しであれば、データ分析基盤構築・MLOps構築支援で対応しています。
導入を見送るべき条件:計測要件が未確定・記事メディア・予算上限
一方、見送りを勧める条件も明確です。計測したい指標が決まっていない段階で導入する案件は失敗します。イベント名の付け方が人によって割れ、半年後には意味の分からないイベントが数百種類並ぶことになるためです。この場合は、KPIを3つに絞ってから着手してください。
記事中心のメディアサイトも見送り対象です。ログイン前提の行動が少なく、ページ単位の指標が主役になるサイトでは、GA4で足ります。無料枠の100万イベントを超える見込みが無いなら、そもそも分析軸をMixpanelへ移す動機が薄い。
月額の上限が決まっていて、自動計測を入れた場合のイベント数が読めない案件も、いったん止めるべきです。Freeで2週間ほど本番相当のトラフィックを流し、実測値を見てから契約する段取りにします。リアルタイム性が要件に入っている場合は、リアルタイム分析とは?バッチとの違いと導入判断の観点で、そもそも必要な鮮度かを先に確かめてください。
Mixpanelの導入でよくある質問:無料枠・GA4との違い・実装の論点
実装と契約の検討でよく挙がる論点を、公式ドキュメントの記載に沿って整理しました。
Mixpanelは無料で使えますか?
Freeプランがあり、月100万イベントまで無料で使えます。保存できるレポートは1シートあたり5件、セッションリプレイは月10,000本、機能フラグは10個までという制限付きです。Growthへ移行しても最初の100万イベントは無料扱いのため、無料枠を超えた瞬間に全量が課金対象になるわけではありません。
MixpanelとGA4はどちらを入れるべきですか?
ログイン後の行動を人単位で追うプロダクトならMixpanel、集客と流入経路の分析が主目的ならGA4が噛み合います。両方入れる構成も珍しくありませんが、ユーザー数の定義が一致しない前提で、指標ごとにどちらを正とするかを先に決めてください。Mixpanelは $user_id で端末をまたいで同一人物に統合するため、数字は構造的にずれます。
Mixpanelのイベント設計は何から決めればよいですか?
KPIを3つに絞り、そこから逆算してイベントを決める順番が手戻りの少ない進め方です。イベント名は「名詞+過去形の動詞」(例:Checkout Completed)で統一し、プロパティ名の命名規則も同時に決めます。プロパティ数の上限は255個未満、ネストの深さは3までという制約があるため、階層の深いJSONをそのまま載せる設計は避けてください。
Mixpanelのデータは日本国内に保存できますか?
公式ドキュメントが示すデータレジデンシーの選択肢は、既定の米国に加えてEU(api-eu.mixpanel.com)とインド(api-in.mixpanel.com)です。日本国内での保管が契約要件に入っている場合は、この構成では満たせません。行動ログは自社の基盤に保持し、Mixpanelへは個人を特定しない集計値だけを送る設計に切り替える判断になります。
Mixpanelのデータを自社のデータ基盤へ取り込めますか?
Data Pipelinesという追加パッケージで、BigQueryなどへエクスポートできます。対象はGrowthまたはEnterpriseの契約で、標準では含まれません。イベントは mp_master_event の1テーブルに集約され、カスタムプロパティはJSON型の properties カラムに入ります。Mixpanelが生成したテーブルのスキーマは変更が禁じられている点にも注意してください。
関連記事
- GA4とは?仕組みとUAとの違い・導入と運用体制の判断まで解説:併用時にユーザー数がずれる理由と、GA4側の運用体制の考え方
- BigQueryとは:サーバーレスDWHの仕組み・料金・できないことと採用判断:エクスポート先のDWHにかかる費用と制約
- ETLとは?仕組み・ELTとの違い・ツール選定から導入判断まで解説:取り込んだ生データを変換する層の設計
- リアルタイム分析とは?バッチとの違いと導入を見送る判断基準を解説:分析の鮮度要件を決めるときの判断軸
- データ分析基盤構築・MLOps構築支援:計測設計からDWH連携までを含めた構築支援