implementing-api-surveys について
アプリ内で PostHog API アンケートを表示し、回答を正しく記録するための実装スキルです。アンケートの取得、アプリ固有 UI への組み込み、イベントプロパティの設定、初回回答の検証を案内します。
主な機能
- 01アンケート定義と質問詳細の取得
- 02アプリ UI と表示トリガーへの組み込み
- 03アンケート進行と回答イベントの記録
- 04送信と重複排除のルール適用
- 05回答と統計の検証
活用シーン
- 01ブラウザーアプリへの PostHog API アンケート追加
- 02途中送信と完了送信の記録
- 03質問との対応関係や回答数の確認
MCP 対応
PostHog ツールでアンケート定義を取得し、回答一覧とアンケート統計を確認します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ ai-plugin --skill implementing-api-surveysインストール後、Claude Code で/implementing-api-surveysを入力して読み込まれたか確認します。
同梱ファイルreferences/event-contract.mdreferences/server-and-mobile.md
詳細
API アンケートの実装
api アンケートは、PostHog 内では定義にすぎません。PostHog が描画することはありません。質問の表示とアンケートイベントの取得は、アプリケーション側で行います。イベントやそのプロパティが正しくない場合、回答が欠落したり、二重にカウントされたり、回答者と紐付けられなくなったりします。
1. アンケートを取得する
id を指定して posthog:survey-get で取得します。各質問の id、type、question、選択肢、尺度、optional に加えて、current_iteration を確認してください。質問 ID を作り出してはいけません。
アンケートがまだ存在しない場合は、まず creating-surveys スキルを使って作成します(種類は api)。設計ガイド(短い質問、評価または選択式を先に、自由記述を後にする)もそちらにあります。ここで繰り返さないでください。
2. ユーザーのコードベースを確認する
UI を作成する前に、以下を確認してください。
- フレームワークと、既存のコンポーネントライブラリまたはデザインシステム。汎用的なモーダルではなく、それらのコンポーネントを使ってアンケートを構築します。
- PostHog の初期化箇所と、インストール済みの SDK およびバージョン(
package.jsonまたはロックファイル、あるいはサーバー言語のマニフェスト)。 - アンケートを表示するタイミング。トリガーはアプリ側で管理します。アンケートのイベント、URL、セレクターの
conditionsは空のままにし、アンケートを表示するタイミングで以下のルックアップを実行してください。getActiveMatchingSurveysは、イベント条件を持つアンケートについて、そのイベントが発生した後でないと返しません。また、その時点でルックアップを再実行する処理もありません。
使用する方法を選びます。
posthog-jsを使うブラウザーアプリ:以下に進みます。- サーバーサイドレンダリングのページ、その他の SDK(Python、Node、Go、Ruby、PHP)、またはカスタムのモバイル UI:server-and-mobile.md を読んでから、手順 5 に進みます。モバイル SDK がネイティブに描画するのはポップオーバー形式のアンケートのみです。そのため、カスタムのモバイル UI ではサーバーの方法に従います。
3. ブラウザーの契約(posthog-js)
posthog-js 1.249.2 以降が必要です。これより古いバージョンでは、キャプチャ時にユーザープロパティと閲覧済み状態が設定されません。手作業で追加させるのではなく、ユーザーにアップグレードを案内してください。
フラグとアンケートバンドルの両方が読み込まれるまでは、ルックアップは機能しません。ターゲティングはフラグを使って評価され、アンケートが読み込まれる前に getActiveMatchingSurveys を呼び出しても何も行われないためです。起動時にそれぞれに対する再試行を 1 つずつ登録してください。また、onFeatureFlags はフラグが再読み込みされるたびに(identify の後、および各回答の後にも)実行されるため、二重に描画されないようにしてください。
let triggered = false
let rendered = false
function tryShowSurvey() {
if (!triggered || rendered) return
posthog.getActiveMatchingSurveys((surveys) => {
const survey = surveys.find((s) => s.id === SURVEY_ID)
if (!survey || rendered) return
rendered = true
renderSurvey(survey)
})
}
// Register once at startup, not per trigger.
posthog.onFeatureFlags(tryShowSurvey)
posthog.onSurveysLoaded(tryShowSurvey)
function showSurveyIfEligible() {
triggered = true
tryShowSurvey()
}
// Call when the survey closes, after the final send or a dismiss.
function onSurveyClosed() {
triggered = false
rendered = false
}
アプリのトリガーから showSurveyIfEligible() を呼び出します。たとえば、チェックアウト完了後や、アンケートをページ読み込み時に表示する場合はセットアップ直後に呼び出します。アンケートを閉じるときは onSurveyClosed() を呼び出してください。これにより、繰り返し表示できるアンケートは次のトリガーで再び表示されます。繰り返せないアンケートは、posthog-js に閲覧済みとして記録されるため、表示されません。シングルページアプリでは、アプリが PostHog を初期化する箇所で 2 つのリスナーを登録し、そのコードがアンマウントされる可能性がある場合は、返された関数を呼び出して登録を解除してください。SURVEY_ID は手順 1 で取得した ID です。renderSurvey は、アプリ独自の UI を使って構築したコンポーネントをマウントし、そのコンポーネントが以下のハンドラーを呼び出します。getActiveMatchingSurveys はこのユーザーに対するアンケートのターゲティングを適用するため、返されたものだけを描画してください。
3 種類のイベントをキャプチャします。answers は各質問 ID とその回答を対応付け、今回の送信でこれまでに入力されたすべての回答を保持します。プロパティの正確な名前と値の形式については、event-contract.md を参照してください。
function onShown(survey) {
posthog.capture('survey shown', {
$survey_id: survey.id,
$survey_iteration: survey.current_iteration,
})
// posthog-js reads this key for the survey wait period; only its own renderer writes it.
try {
localStorage.setItem('lastSeenSurveyDate', new Date().toISOString())
} catch {}
}
function onSubmit(survey, answers, submissionId, completed) {
posthog.capture('survey sent', {
$survey_id: survey.id,
$survey_iteration: survey.current_iteration,
$survey_submission_id: submissionId,
$survey_completed: completed,
$survey_questions: survey.questions.map(({ id, question }) => ({ id, question })),
...Object.fromEntries(
Object.entries(answers).map(([questionId, value]) => [`$survey_response_${questionId}`, value])
),
})
}
function onDismiss(survey) {
posthog.capture('survey dismissed', {
$survey_id: survey.id,
$survey_iteration: survey.current_iteration,
})
}
データに気付かないうちに問題を起こすルール:
- 回答者が回答を開始したときに
$survey_submission_id(crypto.randomUUID())を 1 つ生成し、その回答の送信のたびに同じ値を再利用します。PostHog はこの ID を使って回答を重複排除し、課金対象の回答数を計算します。この ID がないイベントは、それぞれ別の回答としてカウントされます。 - 部分送信では
$survey_completedをfalse、最終送信ではtrueにします。 - 送信のたびに、最新の回答だけではなく、それまでのすべての回答を送信します。PostHog は同じ送信 ID のイベントのうち、最新のものを保持します。
- 評価は posthog-js が送信する形式に合わせて数値で送信します。複数選択は文字列の配列で送信します。回答済みの質問に対してのみ、
$survey_response_<question_id>キーを送信します。 - 「閉じる」とは、回答せずに閉じることを意味します。最終的な
survey sentの後にsurvey dismissedを送信してはいけません。
4. ブラウザーで既読状態を手動設定しないでください
posthog-js は、survey sent または survey dismissed をキャプチャすると、$survey_responded/<id>[/<iteration>] または $survey_dismissed/... と、ローカルの既読フラグを設定します。これにより、アンケートが再度提示されなくなります。これらのプロパティを自分で追加すると、重複して設定されます。
5. 最初の回答を確認する
実際のアプリでアンケートを一度表示して、回答を送信するようユーザーに依頼します。その後、次の手順を実行します。
- アンケートの
idを指定してposthog:surveys-responses-listを呼び出します。行には、サーバー側で解決された質問文が表示されます。回答が正しい質問の下に表示されていることと、複数選択の回答がリストとして届いていることを確認します。 - アンケートの
idを指定してposthog:survey-statsを呼び出します。shownとsentの件数が増えていること、また、1 回の送信が 2 件ではなく 1 件の回答として記録されていることを確認します。 - 何も届かない場合は、プロジェクトトークンと、ライブイベントに
survey sentが表示されていることを確認してから、debugging-surveysに従ってください。推測で判断しないでください。
実装した内容、トリガーの場所、確認済みの回答を報告してください。