前回の記事ではCJOの全体構造を解説した。「すごろく」のメタファーで全体像を掴んでもらった上で、今回はより深い実践内容に踏み込む。
特に、現場で「なぜ動かない?」「どうすれば修正できる?」という壁にぶつかったときに必要な知識を集中して解説する。
「外部セグメント参照」設計——これをやるかやらないかで運用コストが10倍変わる
なぜ外部セグメント参照が必須なのか
CJOの最大の制約は「起動後にジャーニーの構造を編集できない」ことだ。Entry Criteria・Milestone・Exit Criteriaなどの「各種基準」は起動後に一切変更できない。
しかし公式ドキュメントが強調している「抜け道」がある。
「各種基準の中で直接ルールを書かず、外部のバッチセグメントをinclude / excludeするルールだけを書く」という設計だ。
【外部セグメント参照の構造】CJO内の Entry Criteria: 「セグメントAをinclude」だけを記述 ← 起動後変更不可 ↓ 参照外部バッチセグメントA(オーディエンススタジオで管理): 「過去30日以内にサイト訪問 AND 未購買 AND ...」← 起動後でも自由に編集可能!
起動後も外部セグメントは自由に編集できる。よって「外部セグメントのルール変更 → CJOの実質的な基準変更」が実現できる。
「抜け道」を前提とした外部セグメントの命名規則
現場でおすすめする命名規則を紹介する。
命名規則の例[JN_01] 購買育成ジャーニー - ステージ1 - エントリー基準[JN_01] 購買育成ジャーニー - ステージ1 - 終了基準(ドロップアウトリスト)[JN_01] 購買育成ジャーニー - ステージ1 - 終了基準(正常プロファイルexclude用)[JN_01] 購買育成ジャーニー - ステージ2 - マイルストーン[JN_01] 購買育成ジャーニー - ゴール基準
重要: 各外部セグメントは「そのCJOの基準以外からは参照されないようにする」ことが公式ドキュメントの推奨だ。他のジャーニーやセグメントから参照されていると、基準の変更が意図しない影響を与える可能性がある。
Entry Criteriaへの外部セグメント設定手順
セグメントエディタ上で「Drag-on Rules → Existing Segment」を選択すると、外部のバッチセグメントをinclude / excludeするルールが作れる。
Entry Criteriaの設定1. セグメントエディタを開く2. 「Drag-on Rules」から「Existing Segment」を選択3. 「[JN_01] ステージ1 - エントリー基準」セグメントを選択4. 「Include」を選択して保存これだけ。実際の条件ロジックは全て外部セグメント側に書く。
Exit Criteriaの設計——「空のセグメントを2つ用意しておく」という鉄則
公式ドキュメントが強調している「すべてのステージに必ず終了基準を設定する」という推奨には、具体的な設計パターンがある。
なぜ全ステージにExit Criteriaが必要か
「終了基準が必要なさそうなステージ」でも、必ず以下の事態は発生する:
- Entry Criteriaの設定ミスで意図しないプロファイルがエントリーしてしまった
- JumpやRe-entryオプションの影響で意図せず再エントリーしたプロファイルの重複アクティベーションを止めたい
- 特定のオプトアウト顧客をシナリオから外したい
これらは「起動後に発生する」問題だ。Exit Criteriaがないステージでは、こうした緊急事態に対応できない。
推奨設計:空のセグメントを2種類事前作成する
事前に作成しておく外部セグメント(各ステージ用)① ドロップアウトリスト用セグメント(初期は空) → 名前例:[JN_01] ステージ1 - 除外リスト(include用) → 「この中にいるプロファイルを除外したい」時に使う② 正常プロファイル用セグメント(初期は空) → 名前例:[JN_01] ステージ1 - 正常プロファイル(exclude用) → 「この中にいるプロファイル以外を除外したい」時に使う
Exit Criteriaの設定
カスタム基準1(include): 「[JN_01] ステージ1 - 除外リスト」をinclude → 空のうちは誰も除外されない → 緊急時:除外したいプロファイルのtd_client_idをこのセグメントに追加するカスタム基準2(exclude): 「[JN_01] ステージ1 - 正常プロファイル」をexclude → 空のうちは全員が「exclude条件を満たさない=誰も除外されない」状態 → 使い方:逆に「正常なプロファイルのリスト以外を全員除外する」必要が出た時に活用
この設計なら、起動後でも外部セグメントを編集することで緊急対応が可能になる。
Stale Profileの「N+1日ルール」への注意
Exit Criteriaの「古くなったプロファイル(Stale Profile)」設定には重要な落とし穴がある。
公式ドキュメントの記述(重要)
Stale Profileの「Exit at = N日」設定をした場合、ステージのエントリーから数えて、N日ではなくN+1日後にドロップアウトする。
判定条件(公式ドキュメントより)(ステージにエントリーした時のセッションタイムスタンプ)< TD_TIME_ADD(journey WF 更新時のセッションタイムスタンプ, '-Nd')
「30日でドロップアウトさせたい」なら、設定値は29日にする必要がある。
journeyテーブルの読み方——デバッグの最重要スキル
CJOをデバッグする際、最も重要なのが「journey テーブル」の読み方だ。これはCJOが自動的に生成・更新するスナップショットテーブルで、各プロファイルが今どこにいるか、どのステップを通過したかが記録されている。
journeyテーブルの基本仕様
テーブル名:journey_${journey_id}(例:journey_13)記録されるタイムスタンプ: セッションタイムスタンプ(実行された日の00:00のUnixタイム) ※実際の実行時刻ではなく、その日の0時0分のタイムスタンプ
カラムの値パターンと解釈
| intime | outtime | 解釈 |
|---|---|---|
| NULLでない値 | NULL | 今ちょうどここにいる |
| NULLでない値 | NULLでない値(同値) | 通過した(Activation Stepなどは必ず同値になる) |
| NULLでない値 | NULLでない値(異なる値) | 一度ここにいて、後で出た |
| NULL | NULL | 今も過去もここにいたことがない |
journeyテーブルの主要カラム
-- journeyテーブルの主要カラム構成
-- (ステージ0・ステージ1・ゴール・ドロップアウトの例)
SELECT
cdp_customer_id,
-- ジャーニー全体
intime_journey, -- ジャーニーにエントリーした時刻
outtime_journey, -- ジャーニーからドロップアウトした時刻
-- ゴール
intime_goal, -- ゴール基準を満たした時刻
-- ステージ0
intime_stage_0, -- ステージ0にエントリーした時刻
outtime_stage_0, -- ステージ0から出た時刻
intime_stage_0_milestone,-- ステージ0のマイルストーンを満たした時刻
intime_stage_0_exit_0, -- ステージ0の終了基準0を満たした時刻
-- ステージ0の各ステップ(ハッシュ値がステップIDになる)
intime_stage_0_24d42ab6_activation, -- Activation Stepを通過した時刻
outtime_stage_0_24d42ab6_activation, -- 同上(通過なのでintimeと同値)
intime_stage_0_c48862a1_wait, -- Wait Stepに入った時刻
outtime_stage_0_c48862a1_wait, -- Wait Stepを出た時刻(Wait日数後)
-- ステージ1
intime_stage_1,
outtime_stage_1,
intime_stage_1_milestone
FROM journey_13 -- journey_${journey_id}現在進行中のプロファイルの位置を確認するSQL
-- 現在各プロファイルがどのステージ・ステップにいるかを確認する
SELECT
cdp_customer_id,
CASE
WHEN intime_goal IS NOT NULL
THEN 'GOAL'
WHEN outtime_journey IS NOT NULL
THEN 'DROPOUT'
WHEN intime_stage_1 IS NOT NULL AND outtime_stage_1 IS NULL
THEN 'ステージ1(進行中)'
WHEN intime_stage_0 IS NOT NULL AND outtime_stage_0 IS NULL
THEN 'ステージ0(進行中)'
ELSE '未エントリー'
END AS current_position,
-- ステージ0のActivation Stepを通過済みかどうか
CASE
WHEN intime_stage_0_24d42ab6_activation IS NOT NULL
THEN 'アクティベーション済み'
ELSE '未アクティベーション'
END AS activation_status
FROM journey_13
ORDER BY intime_journey DESCアクティベーション済みプロファイルを集計するSQL
-- Activation Stepを通過したプロファイルの日別集計
-- (アクティベーションが実行されたプロファイルの実数確認)
SELECT
TD_TIME_FORMAT(
intime_stage_0_24d42ab6_activation,
'yyyy-MM-dd', 'JST'
) AS activation_date,
COUNT(DISTINCT cdp_customer_id) AS activated_profiles
FROM journey_13
WHERE intime_stage_0_24d42ab6_activation IS NOT NULL
GROUP BY 1
ORDER BY 1 DESCゴール到達率・ドロップアウト率を集計するSQL
-- ジャーニー全体のファネル分析
WITH journey_summary AS (
SELECT
COUNT(DISTINCT cdp_customer_id) AS total_entered,
COUNT(DISTINCT CASE
WHEN intime_stage_1 IS NOT NULL
THEN cdp_customer_id END) AS reached_stage1,
COUNT(DISTINCT CASE
WHEN intime_goal IS NOT NULL
THEN cdp_customer_id END) AS reached_goal,
COUNT(DISTINCT CASE
WHEN outtime_journey IS NOT NULL AND intime_goal IS NULL
THEN cdp_customer_id END) AS dropped_out
FROM journey_13
WHERE intime_journey IS NOT NULL
)
SELECT
total_entered,
reached_stage1,
ROUND(100.0 * reached_stage1 / total_entered, 1) AS stage1_rate_pct,
reached_goal,
ROUND(100.0 * reached_goal / total_entered, 1) AS goal_rate_pct,
dropped_out,
ROUND(100.0 * dropped_out / total_entered, 1) AS dropout_rate_pct
FROM journey_summary起動後のジャーニーを編集したい
CJOの最大の難関が「起動後に構造を変えたいが変えられない」という制約への対処だ。公式ドキュメントが詳細手順を提供しているので、現場目線で整理する。
ケース①:「重複アクティベーションを許容する」場合(簡易版)
重複アクティベーション(元のジャーニーで既に配信を受けた顧客が、新ジャーニーでもう一度最初から配信を受ける)が問題ない場合は、単純な手順で対応できる。
手順:1. 元のジャーニーをコピー(Duplicate Journey)2. コピーしたジャーニーを編集3. 元のジャーニーをポーズ4. コピーしたジャーニーを起動注意点: 元のジャーニーにいたプロファイルも、コピーしたジャーニーに最初からエントリーし直す。 つまり同じシナリオが重複して届く可能性がある。 テストジャーニーや影響が小さい場合は許容できる。
ケース②:「重複アクティベーションを避ける」場合(完全版)
本番運用中のジャーニーを変更する際は、より慎重な手順が必要だ。前提として「全ての基準で外部セグメント参照設計ができていること」が必要になる。
完全な手順(5ステップ):STEP 1:ジャーニーをコピー → コピーしたジャーニーはドラフト状態・プロファイルは空STEP 2:コピーしたジャーニーを編集 → 変更したい部分を修正するSTEP 3:コピーしたジャーニーのEntry Criteriaに「元のジャーニーにいるプロファイルを除外」するルールを追加 → セグメントエディタで「Journey (Stage)」から元のジャーニーを選択してexclude → これにより「元のジャーニーにいる既存プロファイル」がコピーしたジャーニーにエントリーしなくなるSTEP 4:元のジャーニーのEntry Criteria参照セグメントを「誰もエントリーできない状態」に変更 → 外部セグメントのルールを「条件を満たすプロファイルが0になる条件」に変更 → これにより新規プロファイルが元のジャーニーにエントリーしなくなるSTEP 5:STEP 4 と同日に、コピーしたジャーニーを起動 → 翌日から新規プロファイルはコピーしたジャーニーにエントリーする → 元のジャーニーにいた既存プロファイルは元のジャーニーをそのまま進む結果: 既存プロファイル → 元のジャーニーで継続(重複なし) 新規プロファイル → コピーしたジャーニーにエントリー
この手順が成立するためには「外部セグメント参照設計」が事前に完成していることが前提だ。これが「設計段階で外部セグメント参照を徹底する」理由のもう一つの根拠だ。
よくある失敗パターンと対処法——現場経験から
失敗パターン①:「アクティベーションが今日実行されない」
状況: journey WFは正常に完了しているが、今日アクティベーションが実行されない。
診断SQL
-- Activation Stepを本日通過したプロファイルがいるか確認
SELECT COUNT(*) AS count_today
FROM journey_13
WHERE intime_stage_0_24d42ab6_activation =
TD_DATE_TRUNC('day', TD_SCHEDULED_TIME(), 'JST')原因と対処:
- 結果が0件 → プロファイルがまだActivation Stepに到達していない(Wait Step待ちなど)
- 結果が0件 → Entry Criteriaを満たすプロファイルがそもそもいない(外部セグメントの条件確認)
- 結果が0件でない → Activation WFがjourney WFより前に実行されている(スケジュール確認)
失敗パターン②:「ステージが進まない」
状況: プロファイルがステージ0にいるが、ステージ1に移動しない。
診断SQL
-- ステージ0にいてマイルストーンを満たしているが
-- ステージ1に移動していないプロファイルを確認
SELECT
cdp_customer_id,
intime_stage_0,
intime_stage_0_milestone,
intime_stage_1
FROM journey_13
WHERE
intime_stage_0 IS NOT NULL
AND outtime_stage_0 IS NULL -- まだステージ0にいる
AND intime_stage_0_milestone IS NOT NULL -- マイルストーンを満たしている原因: マイルストーンを満たしているのにステージ1に移動しない場合、多くは「外部セグメントの参照しているセグメントの更新が遅れている」か「journey WFがまだ実行されていない(翌日の更新で移動する)」ことが多い。CJOの更新は1日1回なので、マイルストーンを満たした日の翌日に移動するのが正常な動作だ。
失敗パターン③:「Wait Stepの日数が意図と違う」
状況: Wait Stepを5日に設定したが、実際の待機日数がずれている。
重要な理解: Wait Stepはjourney WFの更新回数でカウントする。「5日」とは「5回のjourney WF更新をまたいだ」という意味だ。ペアレントセグメントのスケジュールが毎日実行されていれば5日になるが、途中でポーズしたり、スケジュールが飛んだりすると日数がずれる。
確認SQL
-- Wait Stepの実際の滞在日数を確認
SELECT
cdp_customer_id,
intime_stage_0_c48862a1_wait,
outtime_stage_0_c48862a1_wait,
-- Wait Stepの実際の滞在日数を計算
DATE_DIFF(
'day',
intime_stage_0_c48862a1_wait,
outtime_stage_0_c48862a1_wait
) AS actual_wait_days
FROM journey_13
WHERE
intime_stage_0_c48862a1_wait IS NOT NULL
AND outtime_stage_0_c48862a1_wait IS NOT NULL
ORDER BY actual_wait_days DESCセグメントエディタでのCJO専用機能——「Journey (Stage)」の使い方
CJOを起動すると、オーディエンススタジオのセグメントエディタに「Journey (Stage)」という専用のルール作成オプションが追加される。
Journey (Stage)で何ができるか
利用できる主なシナリオ① 「ジャーニーXのステージYにいる顧客」をセグメント化 → ジャーニーの進行状況に基づいてSQLでセグメントを作れる → 例:「ウィンバックジャーニーのステージ2にいる顧客へのオフライン施策」② 「ジャーニーXにいる顧客」を別のジャーニーのEntry Criteriaからexclude → 「別のジャーニーに既にいる顧客はこのジャーニーにエントリーしない」 → ジャーニー間の重複施策を防ぐ③ 「ジャーニーXのゴールに到達した顧客」をセグメント化 → コンバージョン済み顧客への施策を設計する
Duplicate Journey時のexclude設定(前章の完全手順 STEP3)はまさにこれを使う。
journeyテーブルをSQLで直接使う方法
セグメントエディタのJourney (Stage)機能でなく、SQLを直接書いてジャーニーの状態を分析したい場合
-- ジャーニーIDの特定
-- URL例:https://console-next.treasuredata.com/app/ps/257941/e/13/j/da
-- ペアレントセグメントID:257941 → テーブルプレフィックス:cdp_audience_257941
-- ジャーニーID:13 → テーブル名:journey_13
-- ただしjourney_13テーブルは cdp_audience_257941 データベースに存在する
SELECT *
FROM cdp_audience_257941.journey_13
WHERE intime_journey IS NOT NULL
LIMIT 100CJO設計チェックリスト——起動前に必ず確認する10項目
長年の実装経験から導き出した「起動ボタンを押す前の最終確認リスト」だ。
起動前チェックリスト【構造設計】□ ステージ数は最大8つ以内か□ ステップ数(全ステージ合計)は最大40以内か□ 全てのパスの末尾にEnd Stepがあるか□ Activation StepとActivation Stepの間に必ずWait Stepがあるか【外部セグメント設計】□ 全てのEntry Criteria / Milestone は外部セグメントをinclude/excludeするルールのみで構成されているか□ 全てのExit Criteria は外部セグメントをinclude/excludeするルールのみで構成されているか□ 各外部セグメントは他のジャーニー・セグメントから参照されていないか□ 全ステージにExit Criteriaが設定されているか(空のセグメントで構わない)【スケジュール設計】□ ペアレントセグメントにdailyスケジュールが設定されているか□ journey WFの実行完了時刻がActivation WFの実行開始時刻より前になっているか【Activation Step設計】□ String BuilderにJourney Name・Stage Nameを追加しているか(トラッキング用)□ スケジュールがdailyになっているか(変更不可だが確認)【Goal/Exit設計】□ Goal Criteriaは「コンバージョンの本質的な定義」になっているか□ Exit CriteriaのStale Profileの日数は N+1日ルールを考慮して設定されているか
まとめ:前回記事との組み合わせで完全理解を目指す
前回の記事(全体構造・すごろくメタファー・各ステップの基本)と今回の記事(外部セグメント設計・journeyテーブル・起動後編集手順)を合わせれば、CJOの実装に必要な知識の全体をカバーできる。
特に現場で最も価値が高い知識は以下の3つだ:
- 「外部セグメント参照設計」を最初から徹底すること — 後から後悔しない設計の基本
- 「journeyテーブルをSQLで読める」こと — デバッグとファネル分析の両方に使える
- 「起動後の完全編集手順(5ステップ)」を知っていること — 本番環境での変更対応に必須
CJOは「設計段階の一手間」が「運用段階の安心」に直結するツールだ。「後から直せないかもしれない」という緊張感を持ちながら丁寧に設計することが、長期的な成功への近道だ。
参考ドキュメント
| ページ | URL |
|---|---|
| Entry Criteria / Milestone(外部セグメント参照の推奨) | https://advanced.cdp-academy-lab.com/cjo/ch03_01.html |
| Exit Criteria(空セグメント2種類の推奨設計) | https://advanced.cdp-academy-lab.com/cjo/ch03_03.html |
| Duplicate Journey(完全な起動後編集手順) | https://advanced.cdp-academy-lab.com/cjo/ch04_01.html |
| Journey Tables without Jump(journeyテーブルの仕様) | https://advanced.cdp-academy-lab.com/cjo/ch09_02.html |
| Tips:意図しないプロファイルの除外 | https://advanced.cdp-academy-lab.com/cjo/ch08_01.html |
| Tips:起動中のジャーニーを編集しなければならなくなった時 | https://advanced.cdp-academy-lab.com/cjo/ch08_02.html |