はじめに:解約は気づいたら手遅れ
定期購入(サブスク)型のECで、いちばん怖いのは「解約が売上に出てから気づく」ことです。月次の売上レポートで前月比マイナスが見えた時点では、すでに何十人もの顧客が離れていて、しかもその多くはもう連絡が取れません。
解約という行動は、ある日突然起きるわけではありません。たいていの場合、その数週間から数か月前に「気持ちが離れていく」過程があります。ログインしなくなる、定期便の周期をこっそり延ばす、商品を使い切らずに溜め込む。こうした小さな変化は、売上の数字にはまだ表れていなくても、行動ログにはしっかり残っています。
この記事では、GA4の行動ログと購買データをBigQueryで結合し、「まだ解約していないが、解約しそうな顧客」を早めに見つける仕組みの作り方を解説します。難しい機械学習を最初から組む必要はありません。まずはルールベースで予兆を可視化し、必要になったらBigQuery MLへ広げていく、という現実的な順番で進めます。なお、この記事に出てくる数値はすべて説明のための例です。実際の閾値や精度はお店ごとの商材・周期・顧客層によって大きく変わりますので、必ずご自身のデータで確かめてください。
解約予兆になる行動指標
まず「何を見れば解約の気配がわかるのか」を整理します。定期購入ECでよく予兆として機能する指標は、おおむね次の3系統に分かれます。
エンゲージメントの低下
いちばん素直な予兆が、サイトやアプリへの接触が減ることです。
- ログイン頻度の低下(例:週1回見ていた人が3週間まったく開かなくなる)
- マイページや「次回お届け予定」の閲覧が止まる、通知の開封が減る
満足している顧客ほど「次は何が届くか」を確認したり商品を追加したりするために自然とサイトに戻ってきます。その往復がなくなるのは、関心が薄れているサインです。
定期便そのものへの操作
次に見たいのが、定期便の設定をいじる動きです。これは解約の「予備動作」であることが多い指標です。
- お届け周期の延長(毎月→隔月→3か月ごと、と段階的に間隔を空ける)
- 数量の減少(2個→1個へ)やスキップ(今回お休み)の連続利用
- 配送先・支払い方法の変更画面に来たが、最後まで完了しない
「いきなり解約」よりも、「まず周期を延ばす」「一度スキップする」という形で気持ちが離れていくケースは非常に多いです。ここを捉えられると、かなり早い段階で手を打てます。
不満のシグナル
最後に、明確な不満として表れる行動です。
- 問い合わせ・チャットの利用(特に「解約」「休止」「返品」に関するページの閲覧)
- 解約導線ページ(解約手続き、退会案内)への到達
- 商品レビューでの低評価投稿
解約ページまで来て離脱した(=まだ解約していない)人は、引き止めの最後のチャンスが残っている層です。
GA4行動ログと購買データから特徴量をBigQueryで作る
予兆指標が決まったら、それを顧客ごとの「特徴量(feature)」としてBigQueryに集計します。ここで前提になるのが、GA4のBigQueryエクスポートと、自社の購買・定期便データが同じ顧客IDで結合できることです。GA4側では user_id を計測に流し込み、購買データ側の会員IDと突き合わせられるようにしておきます。
まずはGA4の行動ログから、顧客ごとの直近の動きを集計します。
-- 直近28日間の行動指標を顧客ごとに集計(行動側の特徴量テーブルを作成)
CREATE OR REPLACE TABLE `your_project.churn.behavior_features` AS
WITH events AS (
SELECT
user_id,
event_name,
TIMESTAMP_MICROS(event_timestamp) AS event_ts,
(SELECT value.string_value
FROM UNNEST(event_params)
WHERE key = 'page_location') AS page_location
FROM `your_project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN
FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 28 DAY))
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE('Asia/Tokyo'))
AND user_id IS NOT NULL
)
SELECT
user_id,
COUNTIF(event_name = 'login') AS login_count_28d,
COUNT(DISTINCT DATE(event_ts, 'Asia/Tokyo')) AS active_days_28d,
MAX(event_ts) AS last_seen_ts,
COUNTIF(page_location LIKE '%/subscription/skip%') AS skip_view_28d,
COUNTIF(page_location LIKE '%/contact%') AS contact_view_28d,
COUNTIF(page_location LIKE '%/cancel%') AS cancel_view_28d
FROM events
GROUP BY user_id;
次に、購買・定期便側のデータから、周期や購入間隔の変化を作ります。こちらは自社DBから取り込んだテーブル(ここでは your_project.commerce.subscriptions を想定)を使います。
-- 定期便の状態と直近の購入間隔を顧客ごとに集計(購買側の特徴量テーブルを作成)
CREATE OR REPLACE TABLE `your_project.churn.commerce_features` AS
SELECT
s.user_id,
s.cycle_days AS current_cycle_days, -- 現在のお届け周期
s.cycle_days - s.prev_cycle_days AS cycle_change_days, -- 周期の延長幅(プラスなら延長)
s.skip_count_90d, -- 直近90日のスキップ回数
DATE_DIFF(CURRENT_DATE('Asia/Tokyo'), s.last_order_date, DAY) AS days_since_last_order
FROM `your_project.commerce.subscriptions` AS s
WHERE s.status = 'active';
最後に、いま作った2つのテーブル(behavior_features と commerce_features)を user_id で結合して、1顧客=1行の特徴量テーブルにまとめます。ここで FULL OUTER JOIN を使うのは、片方にしか出てこない顧客(たとえば購買はあるが直近28日まったくサイトに来ていない=行動ログが空の人)を取りこぼさないためです。そのままだと休眠顧客や非定期客も混ざるので、絞り込みは後段のスコアリング側で current_cycle_days IS NOT NULL(=アクティブな定期客)を条件にして行います。
-- 行動ログと購買データを結合した特徴量テーブル
CREATE OR REPLACE TABLE `your_project.churn.features` AS
SELECT
COALESCE(b.user_id, c.user_id) AS user_id, -- どちらか欠けても拾えるように
b.login_count_28d,
b.active_days_28d,
DATE_DIFF(CURRENT_DATE('Asia/Tokyo'),
DATE(b.last_seen_ts, 'Asia/Tokyo'), DAY) AS days_since_last_seen,
b.skip_view_28d,
b.contact_view_28d,
b.cancel_view_28d,
c.current_cycle_days,
c.cycle_change_days,
c.skip_count_90d,
c.days_since_last_order
FROM `your_project.churn.behavior_features` AS b
FULL OUTER JOIN `your_project.churn.commerce_features` AS c
ON b.user_id = c.user_id
これで「いまアクティブな定期購入顧客が、それぞれどんな状態にあるか」が1枚のテーブルで見えるようになります。
スコアリング:ルールから始めてBigQuery MLへ
特徴量がそろったら、各顧客に解約リスクのスコアをつけます。
まずはルールベース
最初から機械学習を組む必要はありません。現場の感覚を素直にルールへ落とすだけでも、十分に役立つアラートが作れます。以下は加点方式の例です(点数・閾値はあくまで例で、自店のデータで調整してください)。
-- ルールベースの解約リスクスコア(加点方式の例)
SELECT
user_id,
(
IF(days_since_last_seen >= 21, 30, 0) + -- 3週間ログインなし
IF(skip_count_90d >= 2, 20, 0) + -- スキップ常用
IF(cycle_change_days > 0, 20, 0) + -- 周期を延長した
IF(cancel_view_28d > 0, 20, 0) + -- 解約ページを見た
IF(contact_view_28d > 0, 10, 0) -- 問い合わせ動線に来た
) AS churn_risk_score
FROM `your_project.churn.features`
WHERE current_cycle_days IS NOT NULL -- アクティブな定期顧客のみ
ORDER BY churn_risk_score DESC
このスコアが一定以上(例:50点以上)の顧客を「予兆あり」として扱います。ルールベースの良いところは、なぜリスクが高いと判定されたのかが一目でわかること、そして外れていたときに閾値をすぐ直せることです。
データが溜まったらBigQuery ML
「過去に解約した顧客」のラベル(解約フラグ)が十分に貯まってきたら、BigQuery MLのロジスティック回帰で確率として予測できます。SQLだけで学習から予測まで完結します。
-- ロジスティック回帰で解約確率を学習
CREATE OR REPLACE MODEL `your_project.churn.churn_model`
OPTIONS (
model_type = 'LOGISTIC_REG',
input_label_cols = ['churned'],
auto_class_weights = TRUE -- 解約は少数派なので不均衡を補正
) AS
SELECT
login_count_28d,
active_days_28d,
days_since_last_seen,
skip_count_90d,
cycle_change_days,
cancel_view_28d,
contact_view_28d,
churned -- 学習用ラベル:その後実際に解約したか(1/0)
FROM `your_project.churn.training_features`;
学習したモデルで、いまアクティブな顧客の解約確率を出します。
-- 現役顧客の解約確率を予測
SELECT
user_id,
predicted_churned_probs[OFFSET(0)].prob AS churn_probability
FROM ML.PREDICT(
MODEL `your_project.churn.churn_model`,
(SELECT * FROM `your_project.churn.features`)
)
ORDER BY churn_probability DESC
どちらが優れているという話ではなく、立ち上げの速さと説明しやすさならルール、ラベルが貯まって精度を追う段階ならML、と使い分けるのが現実的です。
予兆顧客へのアラートと打ち手
スコアが出ても、見るだけでは何も変わりません。予兆が出た顧客のリストを、実際のアクションにつなげる導線が必要です。
定番なのは、スコアの高い顧客リストをBigQueryのスケジュールドクエリで毎朝更新し、それをスプレッドシートやCRM、メール配信ツールへ連携する形です。具体的には次のような運用が考えられます。
- 「周期を延長した」層には、お休み・周期変更の提案メールを先回りで送る
- 「解約ページを見た」層には、解約理由に答えるFAQや、休止という選択肢を案内する
- 高単価・長期の優良顧客でリスクが上がった人だけ、人が個別にフォローする
ポイントは、全員に同じクーポンをばらまかないことです。予兆の「種類」によって刺さる打ち手は違いますし、まだ離れる気のない顧客にまで割引を配ると利益を削るだけになります。
スケジュールドクエリの組み方や、結果をスプレッドシートへ自動連携する具体的な手順は、別記事のBigQuery MLとGeminiでECの購入予測を行う方法でも触れているので、あわせて参考にしてください。
精度とデータ漏洩への注意
最後に、このモデルを運用する上で必ず押さえておきたい注意点です。
⚠️ 学習データに「未来の情報」を混ぜないでください。たとえば「解約した月の行動ログ」を特徴量に入れてしまうと、見かけ上の精度は跳ね上がりますが、それは予測ではなく結果を見ているだけです(データリーケージ)。特徴量は必ず「予測したい時点より前」のデータだけで作るのが鉄則です。
リーケージのほかにも、気をつけたい点がいくつかあります。
- 解約は少数派なので、「全員残る」と予測しても正解率は高く出ます。正解率だけで判断せず、予兆を取りこぼさない指標(再現率)とのバランスで評価してください。
- スコアが高い=必ず解約する、ではありません。「優先して声をかけるべき順番」を決める道具と捉えるのが安全です。
- 行動ログを使った予測は個人の利用状況を扱います。プライバシーポリシーでの説明や社内ルールも忘れずに整え、モデルは定期的に作り直してください(放置すると季節変化で精度が落ちます)。
なお、ここまでに挙げた点数・確率・期間はすべて説明のための例です。どの指標がどれくらい効くかは商材や顧客層によってバラバラなので、まずは自店のデータで小さく試すことをおすすめします。
まとめ
定期購入ECの解約は、売上に表れる前に行動ログへサインが出ています。それを拾うために、この記事では次の流れを紹介しました。
- 解約予兆になる行動指標を、エンゲージメント・定期便操作・不満シグナルの3系統で整理する
- GA4の行動ログと購買・定期便データをBigQueryで結合し、1顧客1行の特徴量テーブルを作る
- まずはルールベースでスコアリングし、ラベルが貯まったらBigQuery MLへ広げる
- 予兆の種類ごとに打ち手を変え、スコアの高い順にフォローする
- データリーケージと評価指標、プライバシーに注意して運用する
最初から完璧なモデルを目指す必要はありません。まずは「ログインが止まった顧客リスト」を毎朝出すだけでも、これまで見えなかった離反予備軍が見えるようになります。同じくGA4×BigQueryで在庫の死に筋を見つけるECの在庫回転率を可視化して死に筋を特定する方法もあわせて読むと、行動ログと業務データを結びつける感覚がつかめるはずです。