<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Analytics on Tarragon</title><link>https://tarrragon.github.io/blog/tags/analytics/</link><description>Recent content in Analytics on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Sat, 20 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/analytics/index.xml" rel="self" type="application/rss+xml"/><item><title>Funnel Analysis</title><link>https://tarrragon.github.io/blog/monitoring/knowledge-cards/funnel-analysis/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/knowledge-cards/funnel-analysis/</guid><description>&lt;p>Funnel analysis 的核心概念是「追蹤使用者在多步驟流程中每一步的轉換率和流失率」。每一步有多少使用者完成、多少使用者離開，構成漏斗形狀的轉換圖。可先對照 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="說明把使用者按共同特徵分群、比較不同群組行為差異的分析方法">cohort analysis&lt;/a>（按群組比較留存）和 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/rfm/" data-link-title="RFM" data-link-desc="說明用 Recency / Frequency / Monetary 三個維度把使用者分成可操作群組的分群方法">RFM&lt;/a>（按行為分群）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Funnel analysis 位在行為資料收集之後、產品決策之前。它的輸入是 event 類監控事件（使用者操作記錄），輸出是每步的轉換率。Funnel analysis 的前提是去識別化（&lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/redaction/" data-link-title="Redaction" data-link-desc="說明在事件資料離開 client 之前把敏感欄位的值替換成遮罩或移除的機制">redaction&lt;/a>）已完成 — 分析行為資料前必須確保資料不含可識別個人的敏感欄位。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>產品需要 funnel analysis 的訊號是「使用者在某個流程中的完成率低於預期，但不知道卡在哪一步」。註冊流程的轉換率從填寫 email 到完成驗證只有 30%，funnel analysis 揭露 60% 的使用者在「等待驗證信」步驟流失。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Funnel analysis 要定義步驟順序、步驟之間的時間窗口（使用者在多久內完成下一步才算轉換）、以及分群維度（按平台、來源、使用者類型拆分 funnel）。步驟定義需要和事件命名規範對齊 — funnel 的每一步對應一個具體的事件名稱。&lt;/p></description><content:encoded><![CDATA[<p>Funnel analysis 的核心概念是「追蹤使用者在多步驟流程中每一步的轉換率和流失率」。每一步有多少使用者完成、多少使用者離開，構成漏斗形狀的轉換圖。可先對照 <a href="/blog/monitoring/knowledge-cards/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="說明把使用者按共同特徵分群、比較不同群組行為差異的分析方法">cohort analysis</a>（按群組比較留存）和 <a href="/blog/monitoring/knowledge-cards/rfm/" data-link-title="RFM" data-link-desc="說明用 Recency / Frequency / Monetary 三個維度把使用者分成可操作群組的分群方法">RFM</a>（按行為分群）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Funnel analysis 位在行為資料收集之後、產品決策之前。它的輸入是 event 類監控事件（使用者操作記錄），輸出是每步的轉換率。Funnel analysis 的前提是去識別化（<a href="/blog/monitoring/knowledge-cards/redaction/" data-link-title="Redaction" data-link-desc="說明在事件資料離開 client 之前把敏感欄位的值替換成遮罩或移除的機制">redaction</a>）已完成 — 分析行為資料前必須確保資料不含可識別個人的敏感欄位。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>產品需要 funnel analysis 的訊號是「使用者在某個流程中的完成率低於預期，但不知道卡在哪一步」。註冊流程的轉換率從填寫 email 到完成驗證只有 30%，funnel analysis 揭露 60% 的使用者在「等待驗證信」步驟流失。</p>
<h2 id="設計責任">設計責任</h2>
<p>Funnel analysis 要定義步驟順序、步驟之間的時間窗口（使用者在多久內完成下一步才算轉換）、以及分群維度（按平台、來源、使用者類型拆分 funnel）。步驟定義需要和事件命名規範對齊 — funnel 的每一步對應一個具體的事件名稱。</p>
]]></content:encoded></item><item><title>行為事件設計</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/</guid><description>&lt;p>行為事件是使用者操作的結構化記錄，每一筆事件回答「誰、在什麼時候、做了什麼、結果如何」。行為分析的品質上限由事件設計決定 — 事件粒度太粗無法回答細節問題，事件粒度太細讓儲存和查詢成本失控。&lt;/p>
&lt;h2 id="事件命名">事件命名&lt;/h2>
&lt;p>行為事件的命名遵循 &lt;code>namespace.action&lt;/code> 格式（&lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/event-naming-convention/" data-link-title="事件命名規範" data-link-desc="namespace.action 格式的事件命名、命名一致性的工程價值、和商業方案命名慣例的對應">模組一 事件命名規範&lt;/a>）。行為分析場景對命名的額外要求是：同一個 funnel 內的事件要能用 namespace 前綴篩選。&lt;/p>
&lt;p>例：註冊流程的事件用共同前綴 &lt;code>signup&lt;/code>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">signup.page.view 使用者看到註冊頁
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">signup.form.submit 使用者送出表單
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">signup.email.verify 使用者點擊驗證信連結
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">signup.complete 註冊完成&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>用 &lt;code>signup.*&lt;/code> 就能篩選出整個註冊流程的事件，不需要事先知道每一步的完整名稱。&lt;/p>
&lt;h2 id="屬性設計">屬性設計&lt;/h2>
&lt;p>每個事件除了名稱，還帶有屬性（properties / parameters）描述事件的 context。屬性分成三層：&lt;/p>
&lt;h3 id="通用屬性每個事件都有">通用屬性（每個事件都有）&lt;/h3>
&lt;ul>
&lt;li>&lt;code>timestamp&lt;/code>：事件發生的時間（UTC，毫秒精度）&lt;/li>
&lt;li>&lt;code>session_id&lt;/code>：當次使用的 session 識別碼&lt;/li>
&lt;li>&lt;code>user_id&lt;/code>：使用者識別碼（去識別化後，見 &lt;a href="https://tarrragon.github.io/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七&lt;/a>）&lt;/li>
&lt;li>&lt;code>platform&lt;/code>：iOS / Android / Web&lt;/li>
&lt;li>&lt;code>app_version&lt;/code>：app 版本號&lt;/li>
&lt;/ul>
&lt;h3 id="事件類型屬性同類事件共有">事件類型屬性（同類事件共有）&lt;/h3>
&lt;ul>
&lt;li>頁面瀏覽事件：&lt;code>page_name&lt;/code>、&lt;code>referrer&lt;/code>&lt;/li>
&lt;li>按鈕點擊事件：&lt;code>button_id&lt;/code>、&lt;code>button_text&lt;/code>&lt;/li>
&lt;li>搜尋事件：&lt;code>query&lt;/code>、&lt;code>result_count&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="事件專屬屬性特定事件才有">事件專屬屬性（特定事件才有）&lt;/h3>
&lt;ul>
&lt;li>&lt;code>signup.form.submit&lt;/code>：&lt;code>form_method&lt;/code>（email / Google / Apple）&lt;/li>
&lt;li>&lt;code>purchase.complete&lt;/code>：&lt;code>amount&lt;/code>、&lt;code>currency&lt;/code>、&lt;code>product_id&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>屬性設計的判斷標準是：這個屬性是否用於回答一個分析問題。「註冊方式的轉換率差異」需要 &lt;code>form_method&lt;/code> 屬性；如果沒有這個分析問題，就不需要這個屬性。&lt;/p>
&lt;h2 id="funnel-定義">Funnel 定義&lt;/h2>
&lt;p>Funnel 是一連串有順序的事件，代表使用者完成一個目標的步驟。Funnel 定義在事件設計階段完成 — 決定哪些事件構成一個 funnel、順序是什麼、每步之間的最大時間間隔。&lt;/p>
&lt;p>定義一個 funnel 需要：&lt;/p>
&lt;p>&lt;strong>步驟清單&lt;/strong>：funnel 包含哪些事件，順序是什麼。&lt;/p>
&lt;p>&lt;strong>時間窗口&lt;/strong>：步驟之間的最大間隔。使用者在步驟 A 之後 30 天才做步驟 B，是否算在同一個 funnel 內？時間窗口的設定取決於業務場景 — 電商結帳 funnel 通常是 30 分鐘，SaaS onboarding funnel 可能是 7 天。&lt;/p>
&lt;p>&lt;strong>完成條件&lt;/strong>：什麼算「完成」funnel。到達最後一步即完成，還是需要特定屬性值（&lt;code>purchase.complete&lt;/code> 且 &lt;code>status = success&lt;/code>）。&lt;/p>
&lt;h2 id="過度收集的成本">過度收集的成本&lt;/h2>
&lt;p>行為事件收集的邊界是「能回答已知的分析問題」。收集超出分析需求的事件有三個成本：&lt;/p>
&lt;p>&lt;strong>儲存成本&lt;/strong>：每個事件佔一行 JSONL。高頻事件（每次滾動、每次 hover）的資料量遠大於低頻事件（按鈕點擊、頁面瀏覽）。&lt;/p>
&lt;p>&lt;strong>隱私風險&lt;/strong>：收集的事件越多，包含可識別個人行為模式的風險越高（&lt;a href="https://tarrragon.github.io/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七 資安與隱私&lt;/a>）。&lt;/p>
&lt;p>&lt;strong>噪音&lt;/strong>：分析時需要從大量事件中篩選出有意義的模式。事件越多，訊噪比越低。&lt;/p>
&lt;p>設計好的行為事件直接成為 &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="使用者在哪一步流失 — 從事件序列計算每步轉換率、找出流失最嚴重的步驟、區分設計問題和技術問題">Funnel analysis&lt;/a> 的輸入 — funnel 的每一步對應一個行為事件。行為事件在四類事件分類中屬於 Event 類，完整的分類定義見&lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/four-event-types/" data-link-title="四類事件的完整定義" data-link-desc="Event / Error / Metric / Lifecycle 四類事件各自的語意、觸發時機和典型用途 — 分類是監控體系的統一語言">模組一 四類事件定義&lt;/a>。收集行為事件前必須完成&lt;a href="https://tarrragon.github.io/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">去識別化&lt;/a> — 使用者行為模式本身就是可識別資訊。&lt;/p></description><content:encoded><![CDATA[<p>行為事件是使用者操作的結構化記錄，每一筆事件回答「誰、在什麼時候、做了什麼、結果如何」。行為分析的品質上限由事件設計決定 — 事件粒度太粗無法回答細節問題，事件粒度太細讓儲存和查詢成本失控。</p>
<h2 id="事件命名">事件命名</h2>
<p>行為事件的命名遵循 <code>namespace.action</code> 格式（<a href="/blog/monitoring/01-mental-model/event-naming-convention/" data-link-title="事件命名規範" data-link-desc="namespace.action 格式的事件命名、命名一致性的工程價值、和商業方案命名慣例的對應">模組一 事件命名規範</a>）。行為分析場景對命名的額外要求是：同一個 funnel 內的事件要能用 namespace 前綴篩選。</p>
<p>例：註冊流程的事件用共同前綴 <code>signup</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">signup.page.view          使用者看到註冊頁
</span></span><span class="line"><span class="ln">2</span><span class="cl">signup.form.submit        使用者送出表單
</span></span><span class="line"><span class="ln">3</span><span class="cl">signup.email.verify       使用者點擊驗證信連結
</span></span><span class="line"><span class="ln">4</span><span class="cl">signup.complete           註冊完成</span></span></code></pre></div><p>用 <code>signup.*</code> 就能篩選出整個註冊流程的事件，不需要事先知道每一步的完整名稱。</p>
<h2 id="屬性設計">屬性設計</h2>
<p>每個事件除了名稱，還帶有屬性（properties / parameters）描述事件的 context。屬性分成三層：</p>
<h3 id="通用屬性每個事件都有">通用屬性（每個事件都有）</h3>
<ul>
<li><code>timestamp</code>：事件發生的時間（UTC，毫秒精度）</li>
<li><code>session_id</code>：當次使用的 session 識別碼</li>
<li><code>user_id</code>：使用者識別碼（去識別化後，見 <a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七</a>）</li>
<li><code>platform</code>：iOS / Android / Web</li>
<li><code>app_version</code>：app 版本號</li>
</ul>
<h3 id="事件類型屬性同類事件共有">事件類型屬性（同類事件共有）</h3>
<ul>
<li>頁面瀏覽事件：<code>page_name</code>、<code>referrer</code></li>
<li>按鈕點擊事件：<code>button_id</code>、<code>button_text</code></li>
<li>搜尋事件：<code>query</code>、<code>result_count</code></li>
</ul>
<h3 id="事件專屬屬性特定事件才有">事件專屬屬性（特定事件才有）</h3>
<ul>
<li><code>signup.form.submit</code>：<code>form_method</code>（email / Google / Apple）</li>
<li><code>purchase.complete</code>：<code>amount</code>、<code>currency</code>、<code>product_id</code></li>
</ul>
<p>屬性設計的判斷標準是：這個屬性是否用於回答一個分析問題。「註冊方式的轉換率差異」需要 <code>form_method</code> 屬性；如果沒有這個分析問題，就不需要這個屬性。</p>
<h2 id="funnel-定義">Funnel 定義</h2>
<p>Funnel 是一連串有順序的事件，代表使用者完成一個目標的步驟。Funnel 定義在事件設計階段完成 — 決定哪些事件構成一個 funnel、順序是什麼、每步之間的最大時間間隔。</p>
<p>定義一個 funnel 需要：</p>
<p><strong>步驟清單</strong>：funnel 包含哪些事件，順序是什麼。</p>
<p><strong>時間窗口</strong>：步驟之間的最大間隔。使用者在步驟 A 之後 30 天才做步驟 B，是否算在同一個 funnel 內？時間窗口的設定取決於業務場景 — 電商結帳 funnel 通常是 30 分鐘，SaaS onboarding funnel 可能是 7 天。</p>
<p><strong>完成條件</strong>：什麼算「完成」funnel。到達最後一步即完成，還是需要特定屬性值（<code>purchase.complete</code> 且 <code>status = success</code>）。</p>
<h2 id="過度收集的成本">過度收集的成本</h2>
<p>行為事件收集的邊界是「能回答已知的分析問題」。收集超出分析需求的事件有三個成本：</p>
<p><strong>儲存成本</strong>：每個事件佔一行 JSONL。高頻事件（每次滾動、每次 hover）的資料量遠大於低頻事件（按鈕點擊、頁面瀏覽）。</p>
<p><strong>隱私風險</strong>：收集的事件越多，包含可識別個人行為模式的風險越高（<a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七 資安與隱私</a>）。</p>
<p><strong>噪音</strong>：分析時需要從大量事件中篩選出有意義的模式。事件越多，訊噪比越低。</p>
<p>設計好的行為事件直接成為 <a href="/blog/monitoring/08-business-analytics/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="使用者在哪一步流失 — 從事件序列計算每步轉換率、找出流失最嚴重的步驟、區分設計問題和技術問題">Funnel analysis</a> 的輸入 — funnel 的每一步對應一個行為事件。行為事件在四類事件分類中屬於 Event 類，完整的分類定義見<a href="/blog/monitoring/01-mental-model/four-event-types/" data-link-title="四類事件的完整定義" data-link-desc="Event / Error / Metric / Lifecycle 四類事件各自的語意、觸發時機和典型用途 — 分類是監控體系的統一語言">模組一 四類事件定義</a>。收集行為事件前必須完成<a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">去識別化</a> — 使用者行為模式本身就是可識別資訊。</p>
]]></content:encoded></item><item><title>Funnel Analysis</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/funnel-analysis/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/funnel-analysis/</guid><description>&lt;p>Funnel analysis 計算使用者在一連串步驟中每一步的轉換率，回答「使用者在哪一步離開」。流失最嚴重的步驟是優化投資報酬率最高的位置 — 修一個步驟的流失比優化所有步驟的體驗更有效。&lt;/p>
&lt;h2 id="基本計算">基本計算&lt;/h2>
&lt;p>Funnel 的每一步有兩個數字：進入人數和完成人數。轉換率 = 完成人數 / 進入人數。&lt;/p>
&lt;p>以四步註冊 funnel 為例：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>步驟&lt;/th>
 &lt;th>進入人數&lt;/th>
 &lt;th>完成人數&lt;/th>
 &lt;th>轉換率&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>看到註冊頁&lt;/td>
 &lt;td>1000&lt;/td>
 &lt;td>1000&lt;/td>
 &lt;td>100%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>填寫表單&lt;/td>
 &lt;td>1000&lt;/td>
 &lt;td>620&lt;/td>
 &lt;td>62%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>送出表單&lt;/td>
 &lt;td>620&lt;/td>
 &lt;td>580&lt;/td>
 &lt;td>93.5%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>完成 email 驗證&lt;/td>
 &lt;td>580&lt;/td>
 &lt;td>310&lt;/td>
 &lt;td>53.4%&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>整體轉換率 = 310 / 1000 = 31%。但更有價值的資訊在每步的轉換率：步驟 2（填寫表單）流失 38%，步驟 4（email 驗證）流失 46.6%。這兩步是優化的優先目標。&lt;/p>
&lt;h2 id="流失原因的區分">流失原因的區分&lt;/h2>
&lt;p>Funnel analysis 指出「哪一步流失」，但不直接回答「為什麼流失」。流失原因需要結合其他資料推斷。&lt;/p>
&lt;h3 id="設計問題導致的流失">設計問題導致的流失&lt;/h3>
&lt;p>使用者看到表單但沒填寫（步驟 2 流失 38%）。可能原因：表單欄位太多、要求的資訊太敏感（信用卡號在註冊階段）、表單 UI 在特定裝置上有問題。&lt;/p>
&lt;p>判斷方式：按平台、裝置、螢幕尺寸細分轉換率。如果 iOS 轉換率 70% 但 Android 只有 45%，可能是 Android 的表單 UI 有問題。&lt;/p>
&lt;h3 id="技術問題導致的流失">技術問題導致的流失&lt;/h3>
&lt;p>使用者送出表單但 email 驗證沒完成（步驟 4 流失 46.6%）。可能原因：驗證信被歸到垃圾郵件、驗證連結過期太快、驗證頁面載入失敗。&lt;/p>
&lt;p>判斷方式：結合 error 事件。如果步驟 4 有大量 &lt;code>signup.email.verify.failed&lt;/code> error，是技術問題；如果沒有 error 但流失高，使用者可能沒收到信或沒看到信。&lt;/p>
&lt;h3 id="意圖問題導致的流失">意圖問題導致的流失&lt;/h3>
&lt;p>使用者到了註冊頁但根本沒打算註冊 — 只是瀏覽。這類流失不是問題，是正常的使用者行為。&lt;/p>
&lt;p>判斷方式：看使用者在流失步驟停留的時間。停留 &amp;lt; 3 秒就離開，可能是誤點或沒有註冊意圖；停留 &amp;gt; 30 秒但沒完成，可能是遇到障礙。&lt;/p>
&lt;h2 id="funnel-的時間窗口">Funnel 的時間窗口&lt;/h2>
&lt;p>同一個使用者在步驟 A 和步驟 B 之間隔了多久，仍算在同一個 funnel 內？時間窗口的設定影響 funnel 的計算結果。&lt;/p>
&lt;p>&lt;strong>窗口太短&lt;/strong>：使用者中途離開稍後回來完成，被計為流失。Funnel 的流失率被高估。&lt;/p>
&lt;p>&lt;strong>窗口太長&lt;/strong>：使用者今天瀏覽、一個月後被廣告重新帶回來完成，兩次獨立的意圖被合併成一個 funnel。轉換率被高估。&lt;/p>
&lt;p>合理的窗口依業務場景而定：電商結帳 funnel 用 30 分鐘到 1 小時，SaaS onboarding 用 7 天，B2B 銷售漏斗用 30-90 天。&lt;/p>
&lt;h2 id="畫面狀態矩陣和-funnel-的關係">畫面狀態矩陣和 funnel 的關係&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/ux-design/knowledge-cards/screen-state-matrix/" data-link-title="畫面狀態矩陣" data-link-desc="說明用四欄表格（顯示/可用操作/進入條件/退出路徑）系統性地暴露畫面導航缺口的設計工具">畫面狀態矩陣&lt;/a>（&lt;a href="https://tarrragon.github.io/blog/ux-design/01-screen-state-machine/" data-link-title="模組一：畫面狀態機設計" data-link-desc="畫面狀態矩陣（顯示 / 操作 / 進入 / 退出）— 退出路徑為空 = UX 死胡同">ux-design 模組一&lt;/a>）描述每個畫面的狀態和轉換。Funnel 描述使用者跨畫面的操作路徑。兩者的對應是：funnel 的每一步通常對應一個畫面狀態的進入事件。&lt;/p>
&lt;p>狀態矩陣中的退出路徑（back 按鈕、取消操作）就是 funnel 的流失點。狀態矩陣的退出路徑為空 = UX 死胡同，funnel 分析中表現為「使用者進入後既沒完成也沒退出 — session 中斷」。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>不同使用者群體的行為差異 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="按共同特徵分群、比較不同群體的留存率和行為差異 — 從「平均值」到「誰在用、誰離開了」">Cohort analysis&lt;/a>&lt;/li>
&lt;li>行為事件的設計 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計&lt;/a>&lt;/li>
&lt;li>自架方案做 funnel → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Funnel analysis 計算使用者在一連串步驟中每一步的轉換率，回答「使用者在哪一步離開」。流失最嚴重的步驟是優化投資報酬率最高的位置 — 修一個步驟的流失比優化所有步驟的體驗更有效。</p>
<h2 id="基本計算">基本計算</h2>
<p>Funnel 的每一步有兩個數字：進入人數和完成人數。轉換率 = 完成人數 / 進入人數。</p>
<p>以四步註冊 funnel 為例：</p>
<table>
  <thead>
      <tr>
          <th>步驟</th>
          <th>進入人數</th>
          <th>完成人數</th>
          <th>轉換率</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>看到註冊頁</td>
          <td>1000</td>
          <td>1000</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>填寫表單</td>
          <td>1000</td>
          <td>620</td>
          <td>62%</td>
      </tr>
      <tr>
          <td>送出表單</td>
          <td>620</td>
          <td>580</td>
          <td>93.5%</td>
      </tr>
      <tr>
          <td>完成 email 驗證</td>
          <td>580</td>
          <td>310</td>
          <td>53.4%</td>
      </tr>
  </tbody>
</table>
<p>整體轉換率 = 310 / 1000 = 31%。但更有價值的資訊在每步的轉換率：步驟 2（填寫表單）流失 38%，步驟 4（email 驗證）流失 46.6%。這兩步是優化的優先目標。</p>
<h2 id="流失原因的區分">流失原因的區分</h2>
<p>Funnel analysis 指出「哪一步流失」，但不直接回答「為什麼流失」。流失原因需要結合其他資料推斷。</p>
<h3 id="設計問題導致的流失">設計問題導致的流失</h3>
<p>使用者看到表單但沒填寫（步驟 2 流失 38%）。可能原因：表單欄位太多、要求的資訊太敏感（信用卡號在註冊階段）、表單 UI 在特定裝置上有問題。</p>
<p>判斷方式：按平台、裝置、螢幕尺寸細分轉換率。如果 iOS 轉換率 70% 但 Android 只有 45%，可能是 Android 的表單 UI 有問題。</p>
<h3 id="技術問題導致的流失">技術問題導致的流失</h3>
<p>使用者送出表單但 email 驗證沒完成（步驟 4 流失 46.6%）。可能原因：驗證信被歸到垃圾郵件、驗證連結過期太快、驗證頁面載入失敗。</p>
<p>判斷方式：結合 error 事件。如果步驟 4 有大量 <code>signup.email.verify.failed</code> error，是技術問題；如果沒有 error 但流失高，使用者可能沒收到信或沒看到信。</p>
<h3 id="意圖問題導致的流失">意圖問題導致的流失</h3>
<p>使用者到了註冊頁但根本沒打算註冊 — 只是瀏覽。這類流失不是問題，是正常的使用者行為。</p>
<p>判斷方式：看使用者在流失步驟停留的時間。停留 &lt; 3 秒就離開，可能是誤點或沒有註冊意圖；停留 &gt; 30 秒但沒完成，可能是遇到障礙。</p>
<h2 id="funnel-的時間窗口">Funnel 的時間窗口</h2>
<p>同一個使用者在步驟 A 和步驟 B 之間隔了多久，仍算在同一個 funnel 內？時間窗口的設定影響 funnel 的計算結果。</p>
<p><strong>窗口太短</strong>：使用者中途離開稍後回來完成，被計為流失。Funnel 的流失率被高估。</p>
<p><strong>窗口太長</strong>：使用者今天瀏覽、一個月後被廣告重新帶回來完成，兩次獨立的意圖被合併成一個 funnel。轉換率被高估。</p>
<p>合理的窗口依業務場景而定：電商結帳 funnel 用 30 分鐘到 1 小時，SaaS onboarding 用 7 天，B2B 銷售漏斗用 30-90 天。</p>
<h2 id="畫面狀態矩陣和-funnel-的關係">畫面狀態矩陣和 funnel 的關係</h2>
<p><a href="/blog/ux-design/knowledge-cards/screen-state-matrix/" data-link-title="畫面狀態矩陣" data-link-desc="說明用四欄表格（顯示/可用操作/進入條件/退出路徑）系統性地暴露畫面導航缺口的設計工具">畫面狀態矩陣</a>（<a href="/blog/ux-design/01-screen-state-machine/" data-link-title="模組一：畫面狀態機設計" data-link-desc="畫面狀態矩陣（顯示 / 操作 / 進入 / 退出）— 退出路徑為空 = UX 死胡同">ux-design 模組一</a>）描述每個畫面的狀態和轉換。Funnel 描述使用者跨畫面的操作路徑。兩者的對應是：funnel 的每一步通常對應一個畫面狀態的進入事件。</p>
<p>狀態矩陣中的退出路徑（back 按鈕、取消操作）就是 funnel 的流失點。狀態矩陣的退出路徑為空 = UX 死胡同，funnel 分析中表現為「使用者進入後既沒完成也沒退出 — session 中斷」。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>不同使用者群體的行為差異 → <a href="/blog/monitoring/08-business-analytics/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="按共同特徵分群、比較不同群體的留存率和行為差異 — 從「平均值」到「誰在用、誰離開了」">Cohort analysis</a></li>
<li>行為事件的設計 → <a href="/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計</a></li>
<li>自架方案做 funnel → <a href="/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析</a></li>
</ul>
]]></content:encoded></item><item><title>Cohort Analysis</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/cohort-analysis/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/cohort-analysis/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="說明把使用者按共同特徵分群、比較不同群組行為差異的分析方法">Cohort analysis&lt;/a> 把使用者按共同特徵分群（cohort），比較不同群體在同一個指標上的表現差異。整體平均留存率 40% 可能隱藏了「1 月註冊的使用者留存 60%、3 月註冊的留存 20%」的差異。Cohort analysis 揭露平均值遮蔽的趨勢。&lt;/p>
&lt;h2 id="cohort-的定義方式">Cohort 的定義方式&lt;/h2>
&lt;h3 id="時間-cohort最常用">時間 cohort（最常用）&lt;/h3>
&lt;p>按使用者完成某個動作的時間分群。「1 月份註冊的使用者」「第 12 週 onboarding 完成的使用者」。&lt;/p>
&lt;p>時間 cohort 回答的問題：產品的留存率是否隨時間改善？新版本上線後註冊的使用者留存是否比舊版本高？&lt;/p>
&lt;h3 id="行為-cohort">行為 cohort&lt;/h3>
&lt;p>按使用者的行為特徵分群。「首次使用就完成購買的使用者」「使用過搜尋功能的使用者」「連續 3 天登入的使用者」。&lt;/p>
&lt;p>行為 cohort 回答的問題：哪些行為和留存相關？做了 X 的使用者留存率是否比沒做 X 的高？&lt;/p>
&lt;h3 id="屬性-cohort">屬性 cohort&lt;/h3>
&lt;p>按使用者的固有屬性分群。「iOS 使用者」「企業方案使用者」「來自特定廣告渠道的使用者」。&lt;/p>
&lt;p>屬性 cohort 回答的問題：不同平台/方案/來源的使用者行為是否不同？&lt;/p>
&lt;h2 id="留存率矩陣">留存率矩陣&lt;/h2>
&lt;p>留存率矩陣是 cohort analysis 最常見的呈現方式。每行代表一個 cohort（例如某月註冊的使用者），每列代表註冊後的第 N 天/週/月，格中的值是該 cohort 在第 N 期仍活躍的比例。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Cohort&lt;/th>
 &lt;th>第 0 週&lt;/th>
 &lt;th>第 1 週&lt;/th>
 &lt;th>第 2 週&lt;/th>
 &lt;th>第 4 週&lt;/th>
 &lt;th>第 8 週&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1 月&lt;/td>
 &lt;td>100%&lt;/td>
 &lt;td>45%&lt;/td>
 &lt;td>32%&lt;/td>
 &lt;td>22%&lt;/td>
 &lt;td>18%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2 月&lt;/td>
 &lt;td>100%&lt;/td>
 &lt;td>48%&lt;/td>
 &lt;td>35%&lt;/td>
 &lt;td>25%&lt;/td>
 &lt;td>20%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3 月&lt;/td>
 &lt;td>100%&lt;/td>
 &lt;td>52%&lt;/td>
 &lt;td>40%&lt;/td>
 &lt;td>30%&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>從這張矩陣可以看到：留存率逐月改善（1 月 → 3 月的第 1 週留存從 45% 升到 52%）。如果 2 月有產品改版，這個改善可能和改版相關。&lt;/p>
&lt;h2 id="cohort-analysis-的判讀">Cohort analysis 的判讀&lt;/h2>
&lt;h3 id="自然衰減-vs-產品問題">自然衰減 vs 產品問題&lt;/h3>
&lt;p>所有產品都有自然衰減 — 使用者隨時間減少是正常的。Cohort analysis 的價值在於區分「正常衰減」和「異常衰減」。&lt;/p>
&lt;p>如果所有 cohort 的衰減曲線形狀相似，衰減是產品層面的結構性問題（例如缺少持續使用的理由）。如果某個 cohort 的衰減明顯比其他 cohort 快，需要調查該 cohort 的特殊情況（當時的產品版本、市場環境、使用者來源）。&lt;/p>
&lt;h3 id="穩態留存">穩態留存&lt;/h3>
&lt;p>留存率通常在某個時間點後趨於穩定 — 留下來的使用者不再大量流失。穩態留存的百分比和到達穩態的時間是產品健康度的核心指標。&lt;/p>
&lt;p>穩態留存高但到達時間長 = 產品有價值但 onboarding 需要改善。穩態留存低 = 產品的持續使用價值不足。&lt;/p>
&lt;h2 id="和-funnel-的關係">和 funnel 的關係&lt;/h2>
&lt;p>Funnel analysis 回答「使用者在哪一步流失」（單次流程），cohort analysis 回答「使用者是否持續回來」（長期行為）。兩者互補：funnel 改善單次流程的轉換率，cohort 追蹤改善是否帶來長期留存的變化。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>使用者從哪來 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/attribution/" data-link-title="Attribution" data-link-desc="使用者從哪來、哪個渠道帶來轉換 — last-touch / first-touch / multi-touch 歸因模型的差異和選擇">Attribution&lt;/a>&lt;/li>
&lt;li>單次流程的流失分析 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="使用者在哪一步流失 — 從事件序列計算每步轉換率、找出流失最嚴重的步驟、區分設計問題和技術問題">Funnel analysis&lt;/a>&lt;/li>
&lt;li>使用者分群的工程實作 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群&lt;/a>&lt;/li>
&lt;li>客戶終身價值 → &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV&lt;/a>&lt;/li>
&lt;li>留存率 → &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p><a href="/blog/monitoring/knowledge-cards/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="說明把使用者按共同特徵分群、比較不同群組行為差異的分析方法">Cohort analysis</a> 把使用者按共同特徵分群（cohort），比較不同群體在同一個指標上的表現差異。整體平均留存率 40% 可能隱藏了「1 月註冊的使用者留存 60%、3 月註冊的留存 20%」的差異。Cohort analysis 揭露平均值遮蔽的趨勢。</p>
<h2 id="cohort-的定義方式">Cohort 的定義方式</h2>
<h3 id="時間-cohort最常用">時間 cohort（最常用）</h3>
<p>按使用者完成某個動作的時間分群。「1 月份註冊的使用者」「第 12 週 onboarding 完成的使用者」。</p>
<p>時間 cohort 回答的問題：產品的留存率是否隨時間改善？新版本上線後註冊的使用者留存是否比舊版本高？</p>
<h3 id="行為-cohort">行為 cohort</h3>
<p>按使用者的行為特徵分群。「首次使用就完成購買的使用者」「使用過搜尋功能的使用者」「連續 3 天登入的使用者」。</p>
<p>行為 cohort 回答的問題：哪些行為和留存相關？做了 X 的使用者留存率是否比沒做 X 的高？</p>
<h3 id="屬性-cohort">屬性 cohort</h3>
<p>按使用者的固有屬性分群。「iOS 使用者」「企業方案使用者」「來自特定廣告渠道的使用者」。</p>
<p>屬性 cohort 回答的問題：不同平台/方案/來源的使用者行為是否不同？</p>
<h2 id="留存率矩陣">留存率矩陣</h2>
<p>留存率矩陣是 cohort analysis 最常見的呈現方式。每行代表一個 cohort（例如某月註冊的使用者），每列代表註冊後的第 N 天/週/月，格中的值是該 cohort 在第 N 期仍活躍的比例。</p>
<table>
  <thead>
      <tr>
          <th>Cohort</th>
          <th>第 0 週</th>
          <th>第 1 週</th>
          <th>第 2 週</th>
          <th>第 4 週</th>
          <th>第 8 週</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1 月</td>
          <td>100%</td>
          <td>45%</td>
          <td>32%</td>
          <td>22%</td>
          <td>18%</td>
      </tr>
      <tr>
          <td>2 月</td>
          <td>100%</td>
          <td>48%</td>
          <td>35%</td>
          <td>25%</td>
          <td>20%</td>
      </tr>
      <tr>
          <td>3 月</td>
          <td>100%</td>
          <td>52%</td>
          <td>40%</td>
          <td>30%</td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>從這張矩陣可以看到：留存率逐月改善（1 月 → 3 月的第 1 週留存從 45% 升到 52%）。如果 2 月有產品改版，這個改善可能和改版相關。</p>
<h2 id="cohort-analysis-的判讀">Cohort analysis 的判讀</h2>
<h3 id="自然衰減-vs-產品問題">自然衰減 vs 產品問題</h3>
<p>所有產品都有自然衰減 — 使用者隨時間減少是正常的。Cohort analysis 的價值在於區分「正常衰減」和「異常衰減」。</p>
<p>如果所有 cohort 的衰減曲線形狀相似，衰減是產品層面的結構性問題（例如缺少持續使用的理由）。如果某個 cohort 的衰減明顯比其他 cohort 快，需要調查該 cohort 的特殊情況（當時的產品版本、市場環境、使用者來源）。</p>
<h3 id="穩態留存">穩態留存</h3>
<p>留存率通常在某個時間點後趨於穩定 — 留下來的使用者不再大量流失。穩態留存的百分比和到達穩態的時間是產品健康度的核心指標。</p>
<p>穩態留存高但到達時間長 = 產品有價值但 onboarding 需要改善。穩態留存低 = 產品的持續使用價值不足。</p>
<h2 id="和-funnel-的關係">和 funnel 的關係</h2>
<p>Funnel analysis 回答「使用者在哪一步流失」（單次流程），cohort analysis 回答「使用者是否持續回來」（長期行為）。兩者互補：funnel 改善單次流程的轉換率，cohort 追蹤改善是否帶來長期留存的變化。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>使用者從哪來 → <a href="/blog/monitoring/08-business-analytics/attribution/" data-link-title="Attribution" data-link-desc="使用者從哪來、哪個渠道帶來轉換 — last-touch / first-touch / multi-touch 歸因模型的差異和選擇">Attribution</a></li>
<li>單次流程的流失分析 → <a href="/blog/monitoring/08-business-analytics/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="使用者在哪一步流失 — 從事件序列計算每步轉換率、找出流失最嚴重的步驟、區分設計問題和技術問題">Funnel analysis</a></li>
<li>使用者分群的工程實作 → <a href="/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群</a></li>
<li>客戶終身價值 → <a href="/blog/business/knowledge-cards/ltv/" data-link-title="LTV" data-link-desc="說明客戶終身價值與其在估值中的作用">LTV</a></li>
<li>留存率 → <a href="/blog/business/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明客戶留存率與其對單位經濟的決定作用">Retention</a></li>
</ul>
]]></content:encoded></item><item><title>Cohort Analysis</title><link>https://tarrragon.github.io/blog/monitoring/knowledge-cards/cohort-analysis/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/knowledge-cards/cohort-analysis/</guid><description>&lt;p>Cohort analysis 的核心概念是「把使用者按共同特徵分群，比較不同群組的行為差異」。Cohort 通常按時間（註冊月份）、行為（首次使用的功能）、或屬性（付費方案）分群。可先對照 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="說明追蹤使用者在多步驟流程中每一步的轉換率和流失率的分析方法">funnel analysis&lt;/a>（追蹤單一流程的每步轉換）和 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/rfm/" data-link-title="RFM" data-link-desc="說明用 Recency / Frequency / Monetary 三個維度把使用者分成可操作群組的分群方法">RFM&lt;/a>（按行為指標分群）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cohort analysis 位在 funnel analysis 之後、策略制定之前。Funnel analysis 回答「使用者在哪一步流失」，cohort analysis 回答「哪種使用者流失率高」。兩者搭配使用：funnel 找到流失步驟，cohort 找到流失群組，策略針對特定群組的流失步驟設計。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>產品需要 cohort analysis 的訊號是「整體留存率或轉換率的平均值遮蔽了群組差異」。整體 30 天留存率 40%，但按註冊來源拆分後發現自然搜尋來的使用者留存 60%、廣告來的使用者留存 20% — 平均值沒有揭露這個差異。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cohort analysis 要定義分群維度（按什麼特徵分）、觀察指標（留存率、活躍度、付費率）、觀察時間窗口（7 天、30 天、90 天）、以及最小群組大小（群組太小時統計不顯著）。分群維度的選擇決定了分析能揭露什麼 — 按「註冊來源」分群能看到獲客通路的品質差異，按「使用的功能」分群能看到功能黏著度差異。&lt;/p></description><content:encoded><![CDATA[<p>Cohort analysis 的核心概念是「把使用者按共同特徵分群，比較不同群組的行為差異」。Cohort 通常按時間（註冊月份）、行為（首次使用的功能）、或屬性（付費方案）分群。可先對照 <a href="/blog/monitoring/knowledge-cards/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="說明追蹤使用者在多步驟流程中每一步的轉換率和流失率的分析方法">funnel analysis</a>（追蹤單一流程的每步轉換）和 <a href="/blog/monitoring/knowledge-cards/rfm/" data-link-title="RFM" data-link-desc="說明用 Recency / Frequency / Monetary 三個維度把使用者分成可操作群組的分群方法">RFM</a>（按行為指標分群）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cohort analysis 位在 funnel analysis 之後、策略制定之前。Funnel analysis 回答「使用者在哪一步流失」，cohort analysis 回答「哪種使用者流失率高」。兩者搭配使用：funnel 找到流失步驟，cohort 找到流失群組，策略針對特定群組的流失步驟設計。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>產品需要 cohort analysis 的訊號是「整體留存率或轉換率的平均值遮蔽了群組差異」。整體 30 天留存率 40%，但按註冊來源拆分後發現自然搜尋來的使用者留存 60%、廣告來的使用者留存 20% — 平均值沒有揭露這個差異。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cohort analysis 要定義分群維度（按什麼特徵分）、觀察指標（留存率、活躍度、付費率）、觀察時間窗口（7 天、30 天、90 天）、以及最小群組大小（群組太小時統計不顯著）。分群維度的選擇決定了分析能揭露什麼 — 按「註冊來源」分群能看到獲客通路的品質差異，按「使用的功能」分群能看到功能黏著度差異。</p>
]]></content:encoded></item><item><title>Firebase 套件</title><link>https://tarrragon.github.io/blog/monitoring/06-commercial-comparison/firebase-suite/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/06-commercial-comparison/firebase-suite/</guid><description>&lt;p>Firebase 把 client-side 監控拆成多個獨立產品：Crashlytics 負責 crash 報告、Analytics（GA4）負責行為分析、Remote Config 負責功能旗標和 A/B test。三個產品各自有 SDK、dashboard 和計費模型，但共享 Firebase project 的使用者識別。&lt;/p>
&lt;h2 id="crashlytics">Crashlytics&lt;/h2>
&lt;p>Firebase Crashlytics 專注在 crash 報告 — fatal crash（app 當機）和 non-fatal exception（被捕獲但值得記錄的錯誤）。&lt;/p>
&lt;h3 id="自動-crash-報告">自動 crash 報告&lt;/h3>
&lt;p>Crashlytics SDK 在 app crash 時自動收集 crash 資訊（stack trace、device info、OS version），在下次 app 啟動時上傳。不需要開發者寫程式碼 — SDK 初始化後自動運作。&lt;/p>
&lt;h3 id="issue-分群">Issue 分群&lt;/h3>
&lt;p>和 Sentry 類似，Crashlytics 用 stack trace 自動把 crash 分群成 issue。每個 issue 有影響的使用者數、趨勢、crash-free session 比率。&lt;/p>
&lt;h3 id="和-analytics-的關聯">和 Analytics 的關聯&lt;/h3>
&lt;p>Crashlytics 可以在 crash 報告中附加 Analytics 的使用者屬性和自訂 key。但兩者的 dashboard 獨立 — crash 資料在 Crashlytics console，行為資料在 Analytics console。要從「crash」追蹤到「crash 前使用者做了什麼」需要在兩個 console 之間切換。&lt;/p>
&lt;h2 id="analyticsga4">Analytics（GA4）&lt;/h2>
&lt;p>Firebase Analytics 是 Google Analytics 4（GA4）的 mobile SDK 版本。記錄使用者操作事件（screen view、button click、purchase）和使用者屬性。&lt;/p>
&lt;h3 id="自動收集事件">自動收集事件&lt;/h3>
&lt;p>GA4 SDK 自動收集一組預定義事件：&lt;code>first_open&lt;/code>、&lt;code>session_start&lt;/code>、&lt;code>screen_view&lt;/code>、&lt;code>user_engagement&lt;/code>。開發者不需要手動埋點就能得到基礎的使用統計。&lt;/p>
&lt;h3 id="自訂事件">自訂事件&lt;/h3>
&lt;p>開發者用 &lt;code>logEvent(name, parameters)&lt;/code> 記錄自訂事件。事件名稱和參數的命名有限制（名稱 40 字元、參數 25 個、參數值 100 字元）。&lt;/p>
&lt;h3 id="和四類事件的對應">和四類事件的對應&lt;/h3>
&lt;p>GA4 主要處理 Event 類和 Lifecycle 類事件（&lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/four-event-types/" data-link-title="四類事件的完整定義" data-link-desc="Event / Error / Metric / Lifecycle 四類事件各自的語意、觸發時機和典型用途 — 分類是監控體系的統一語言">模組一&lt;/a>）。Error 類由 Crashlytics 處理。Metric 類沒有原生支援 — 需要把 metric 包裝成 event 的 parameter。&lt;/p>
&lt;h2 id="remote-config">Remote Config&lt;/h2>
&lt;p>Firebase Remote Config 讓開發者在不更新 app 的情況下修改 app 的行為 — 功能旗標（feature flag）、UI 文案、數值參數。&lt;/p>
&lt;h3 id="和-ab-test-的整合">和 A/B test 的整合&lt;/h3>
&lt;p>Remote Config 和 Firebase A/B Testing 整合：定義實驗（variant A: 舊 UI / variant B: 新 UI），Remote Config 自動分配使用者到 variant，Analytics 收集兩組使用者的行為數據，A/B Testing console 顯示統計結果。&lt;/p>
&lt;p>這個整合是 Firebase 生態的獨特優勢 — config 分發、使用者分群、行為收集、統計分析在同一個平台完成，不需要整合多個工具。&lt;/p>
&lt;h2 id="firebase-的取捨">Firebase 的取捨&lt;/h2>
&lt;p>Firebase 的設計取捨是「拆分但整合」— 每個產品獨立運作（可以只用 Crashlytics 不用 Analytics），但組合使用時有整合優勢（Crashlytics + Analytics 的 user ID 共享）。&lt;/p></description><content:encoded><![CDATA[<p>Firebase 把 client-side 監控拆成多個獨立產品：Crashlytics 負責 crash 報告、Analytics（GA4）負責行為分析、Remote Config 負責功能旗標和 A/B test。三個產品各自有 SDK、dashboard 和計費模型，但共享 Firebase project 的使用者識別。</p>
<h2 id="crashlytics">Crashlytics</h2>
<p>Firebase Crashlytics 專注在 crash 報告 — fatal crash（app 當機）和 non-fatal exception（被捕獲但值得記錄的錯誤）。</p>
<h3 id="自動-crash-報告">自動 crash 報告</h3>
<p>Crashlytics SDK 在 app crash 時自動收集 crash 資訊（stack trace、device info、OS version），在下次 app 啟動時上傳。不需要開發者寫程式碼 — SDK 初始化後自動運作。</p>
<h3 id="issue-分群">Issue 分群</h3>
<p>和 Sentry 類似，Crashlytics 用 stack trace 自動把 crash 分群成 issue。每個 issue 有影響的使用者數、趨勢、crash-free session 比率。</p>
<h3 id="和-analytics-的關聯">和 Analytics 的關聯</h3>
<p>Crashlytics 可以在 crash 報告中附加 Analytics 的使用者屬性和自訂 key。但兩者的 dashboard 獨立 — crash 資料在 Crashlytics console，行為資料在 Analytics console。要從「crash」追蹤到「crash 前使用者做了什麼」需要在兩個 console 之間切換。</p>
<h2 id="analyticsga4">Analytics（GA4）</h2>
<p>Firebase Analytics 是 Google Analytics 4（GA4）的 mobile SDK 版本。記錄使用者操作事件（screen view、button click、purchase）和使用者屬性。</p>
<h3 id="自動收集事件">自動收集事件</h3>
<p>GA4 SDK 自動收集一組預定義事件：<code>first_open</code>、<code>session_start</code>、<code>screen_view</code>、<code>user_engagement</code>。開發者不需要手動埋點就能得到基礎的使用統計。</p>
<h3 id="自訂事件">自訂事件</h3>
<p>開發者用 <code>logEvent(name, parameters)</code> 記錄自訂事件。事件名稱和參數的命名有限制（名稱 40 字元、參數 25 個、參數值 100 字元）。</p>
<h3 id="和四類事件的對應">和四類事件的對應</h3>
<p>GA4 主要處理 Event 類和 Lifecycle 類事件（<a href="/blog/monitoring/01-mental-model/four-event-types/" data-link-title="四類事件的完整定義" data-link-desc="Event / Error / Metric / Lifecycle 四類事件各自的語意、觸發時機和典型用途 — 分類是監控體系的統一語言">模組一</a>）。Error 類由 Crashlytics 處理。Metric 類沒有原生支援 — 需要把 metric 包裝成 event 的 parameter。</p>
<h2 id="remote-config">Remote Config</h2>
<p>Firebase Remote Config 讓開發者在不更新 app 的情況下修改 app 的行為 — 功能旗標（feature flag）、UI 文案、數值參數。</p>
<h3 id="和-ab-test-的整合">和 A/B test 的整合</h3>
<p>Remote Config 和 Firebase A/B Testing 整合：定義實驗（variant A: 舊 UI / variant B: 新 UI），Remote Config 自動分配使用者到 variant，Analytics 收集兩組使用者的行為數據，A/B Testing console 顯示統計結果。</p>
<p>這個整合是 Firebase 生態的獨特優勢 — config 分發、使用者分群、行為收集、統計分析在同一個平台完成，不需要整合多個工具。</p>
<h2 id="firebase-的取捨">Firebase 的取捨</h2>
<p>Firebase 的設計取捨是「拆分但整合」— 每個產品獨立運作（可以只用 Crashlytics 不用 Analytics），但組合使用時有整合優勢（Crashlytics + Analytics 的 user ID 共享）。</p>
<table>
  <thead>
      <tr>
          <th>優勢</th>
          <th>代價</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>自動收集、零配置啟動</td>
          <td>自訂彈性受限（事件命名限制、參數數量限制）</td>
      </tr>
      <tr>
          <td>Crashlytics 免費且無量限制</td>
          <td>Analytics 的進階功能需要 BigQuery export（另收費）</td>
      </tr>
      <tr>
          <td>A/B test 整合開箱即用</td>
          <td>鎖定 Google 生態（資料 export 有限制）</td>
      </tr>
      <tr>
          <td>Mobile 優先，Flutter 支援佳</td>
          <td>Web 的支援較弱（GA4 web 是獨立產品線）</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Datadog 的全棧 APM → <a href="/blog/monitoring/06-commercial-comparison/datadog-rum/" data-link-title="Datadog RUM" data-link-desc="全棧 APM 的 client-side 觀點 — client action 到 server trace 的完整鏈路追蹤">Datadog RUM</a></li>
<li>行為分析專用方案 → <a href="/blog/monitoring/06-commercial-comparison/mixpanel-amplitude/" data-link-title="Mixpanel / Amplitude" data-link-desc="行為分析專用方案 vs 通用監控的差異 — Mixpanel 和 Amplitude 的 funnel / cohort / retention 分析能力">Mixpanel / Amplitude</a></li>
<li>自架 vs 商業的判斷 → <a href="/blog/monitoring/06-commercial-comparison/self-hosted-vs-commercial/" data-link-title="自架 vs 商業的判斷決策表" data-link-desc="使用者數、網路範圍、功能需求、合規要求四個維度判斷該自架還是用商業方案">自架 vs 商業的判斷決策表</a></li>
</ul>
]]></content:encoded></item><item><title>Attribution</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/attribution/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/attribution/</guid><description>&lt;p>Attribution（歸因）回答「使用者的轉換應該歸功於哪個渠道或觸點」。使用者可能先看到 Facebook 廣告、再 Google 搜尋、最後直接輸入網址完成購買 — 三個渠道都接觸了使用者，轉換功勞歸誰決定了行銷預算的分配。&lt;/p>
&lt;h2 id="歸因模型">歸因模型&lt;/h2>
&lt;h3 id="last-touch-attribution">Last-touch attribution&lt;/h3>
&lt;p>把轉換功勞全部歸給使用者轉換前最後接觸的渠道。上例中功勞歸「直接輸入網址」。&lt;/p>
&lt;p>優點：實作最簡單 — 只需要記錄轉換事件的 referrer 或 UTM 參數。&lt;/p>
&lt;p>缺點：忽略了前面渠道的貢獻。Facebook 廣告讓使用者第一次知道產品，但在 last-touch 模型中功勞為零。長期使用 last-touch 會導致行銷預算過度集中在「最後一步」渠道（品牌搜尋、直接訪問），低估「認知階段」渠道（展示廣告、社群媒體）。&lt;/p>
&lt;h3 id="first-touch-attribution">First-touch attribution&lt;/h3>
&lt;p>把轉換功勞全部歸給使用者第一次接觸的渠道。上例中功勞歸 Facebook 廣告。&lt;/p>
&lt;p>優點：強調「獲客」渠道的貢獻，適合評估品牌認知和獲客效率。&lt;/p>
&lt;p>缺點：忽略了後續渠道的推進作用。使用者第一次看到廣告但沒行動，可能是後續的 Google 搜尋才促成轉換。&lt;/p>
&lt;h3 id="multi-touch-attribution">Multi-touch attribution&lt;/h3>
&lt;p>把轉換功勞分配給使用者轉換路徑上的所有渠道。分配方式有多種：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>線性歸因&lt;/strong>：每個渠道平均分配。三個渠道各得 33.3%。&lt;/li>
&lt;li>&lt;strong>時間衰減&lt;/strong>：離轉換越近的渠道得到越多功勞。&lt;/li>
&lt;li>&lt;strong>Position-based（U 型）&lt;/strong>：第一個和最後一個渠道各得 40%，中間渠道分 20%。&lt;/li>
&lt;li>&lt;strong>資料驅動（data-driven）&lt;/strong>：用機器學習模型從歷史資料學習每個渠道的貢獻。需要大量資料。&lt;/li>
&lt;/ul>
&lt;h2 id="技術實作">技術實作&lt;/h2>
&lt;p>Attribution 的技術實作需要解決兩個問題：跨 session 的使用者識別，和觸點的記錄。&lt;/p>
&lt;h3 id="跨-session-識別">跨 session 識別&lt;/h3>
&lt;p>同一個使用者在不同 session、不同裝置、不同瀏覽器上的行為需要關聯到同一個人。&lt;/p>
&lt;p>Web 端用 cookie（first-party）或 login ID 關聯。Mobile 端用 device ID 或 login ID。跨裝置關聯需要使用者登入 — 未登入的使用者在不同裝置上是不同的匿名 ID。&lt;/p>
&lt;h3 id="觸點記錄">觸點記錄&lt;/h3>
&lt;p>每次使用者接觸產品的渠道需要記錄。Web 端記錄 referrer、UTM 參數（&lt;code>utm_source&lt;/code>、&lt;code>utm_medium&lt;/code>、&lt;code>utm_campaign&lt;/code>）。Mobile 端記錄 deep link 參數、app store 來源（需要 attribution SDK 如 AppsFlyer、Adjust）。&lt;/p>
&lt;h2 id="自架方案的歸因能力">自架方案的歸因能力&lt;/h2>
&lt;p>自架 collector 能做基礎的 last-touch attribution — 在轉換事件的屬性中記錄 referrer 和 UTM 參數。&lt;/p>
&lt;p>Multi-touch attribution 需要跨 session 的使用者行為歷史，實作複雜度顯著上升。如果 multi-touch 是核心需求，商業方案（GA4、Mixpanel、AppsFlyer）通常比自架更實用。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>A/B test 驗證渠道效果 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/ab-test-statistics/" data-link-title="A/B Test 的統計基礎" data-link-desc="假設檢定、樣本量計算、多重比較校正 — A/B test 不只是「比較兩個數字」，統計方法決定結論是否可靠">A/B test 的統計基礎&lt;/a>&lt;/li>
&lt;li>使用者分群 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="按共同特徵分群、比較不同群體的留存率和行為差異 — 從「平均值」到「誰在用、誰離開了」">Cohort analysis&lt;/a>&lt;/li>
&lt;li>行為事件設計 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計&lt;/a>&lt;/li>
&lt;li>客戶取得成本 → &lt;a href="https://tarrragon.github.io/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Attribution（歸因）回答「使用者的轉換應該歸功於哪個渠道或觸點」。使用者可能先看到 Facebook 廣告、再 Google 搜尋、最後直接輸入網址完成購買 — 三個渠道都接觸了使用者，轉換功勞歸誰決定了行銷預算的分配。</p>
<h2 id="歸因模型">歸因模型</h2>
<h3 id="last-touch-attribution">Last-touch attribution</h3>
<p>把轉換功勞全部歸給使用者轉換前最後接觸的渠道。上例中功勞歸「直接輸入網址」。</p>
<p>優點：實作最簡單 — 只需要記錄轉換事件的 referrer 或 UTM 參數。</p>
<p>缺點：忽略了前面渠道的貢獻。Facebook 廣告讓使用者第一次知道產品，但在 last-touch 模型中功勞為零。長期使用 last-touch 會導致行銷預算過度集中在「最後一步」渠道（品牌搜尋、直接訪問），低估「認知階段」渠道（展示廣告、社群媒體）。</p>
<h3 id="first-touch-attribution">First-touch attribution</h3>
<p>把轉換功勞全部歸給使用者第一次接觸的渠道。上例中功勞歸 Facebook 廣告。</p>
<p>優點：強調「獲客」渠道的貢獻，適合評估品牌認知和獲客效率。</p>
<p>缺點：忽略了後續渠道的推進作用。使用者第一次看到廣告但沒行動，可能是後續的 Google 搜尋才促成轉換。</p>
<h3 id="multi-touch-attribution">Multi-touch attribution</h3>
<p>把轉換功勞分配給使用者轉換路徑上的所有渠道。分配方式有多種：</p>
<ul>
<li><strong>線性歸因</strong>：每個渠道平均分配。三個渠道各得 33.3%。</li>
<li><strong>時間衰減</strong>：離轉換越近的渠道得到越多功勞。</li>
<li><strong>Position-based（U 型）</strong>：第一個和最後一個渠道各得 40%，中間渠道分 20%。</li>
<li><strong>資料驅動（data-driven）</strong>：用機器學習模型從歷史資料學習每個渠道的貢獻。需要大量資料。</li>
</ul>
<h2 id="技術實作">技術實作</h2>
<p>Attribution 的技術實作需要解決兩個問題：跨 session 的使用者識別，和觸點的記錄。</p>
<h3 id="跨-session-識別">跨 session 識別</h3>
<p>同一個使用者在不同 session、不同裝置、不同瀏覽器上的行為需要關聯到同一個人。</p>
<p>Web 端用 cookie（first-party）或 login ID 關聯。Mobile 端用 device ID 或 login ID。跨裝置關聯需要使用者登入 — 未登入的使用者在不同裝置上是不同的匿名 ID。</p>
<h3 id="觸點記錄">觸點記錄</h3>
<p>每次使用者接觸產品的渠道需要記錄。Web 端記錄 referrer、UTM 參數（<code>utm_source</code>、<code>utm_medium</code>、<code>utm_campaign</code>）。Mobile 端記錄 deep link 參數、app store 來源（需要 attribution SDK 如 AppsFlyer、Adjust）。</p>
<h2 id="自架方案的歸因能力">自架方案的歸因能力</h2>
<p>自架 collector 能做基礎的 last-touch attribution — 在轉換事件的屬性中記錄 referrer 和 UTM 參數。</p>
<p>Multi-touch attribution 需要跨 session 的使用者行為歷史，實作複雜度顯著上升。如果 multi-touch 是核心需求，商業方案（GA4、Mixpanel、AppsFlyer）通常比自架更實用。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>A/B test 驗證渠道效果 → <a href="/blog/monitoring/08-business-analytics/ab-test-statistics/" data-link-title="A/B Test 的統計基礎" data-link-desc="假設檢定、樣本量計算、多重比較校正 — A/B test 不只是「比較兩個數字」，統計方法決定結論是否可靠">A/B test 的統計基礎</a></li>
<li>使用者分群 → <a href="/blog/monitoring/08-business-analytics/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="按共同特徵分群、比較不同群體的留存率和行為差異 — 從「平均值」到「誰在用、誰離開了」">Cohort analysis</a></li>
<li>行為事件設計 → <a href="/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計</a></li>
<li>客戶取得成本 → <a href="/blog/business/knowledge-cards/cac/" data-link-title="CAC" data-link-desc="說明獲客成本及其對商業模式可行性的決定作用">CAC</a></li>
</ul>
]]></content:encoded></item><item><title>RFM</title><link>https://tarrragon.github.io/blog/monitoring/knowledge-cards/rfm/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/knowledge-cards/rfm/</guid><description>&lt;p>RFM 的核心概念是「用 Recency（最近活躍度）、Frequency（使用頻率）、Monetary（貢獻價值）三個維度把使用者分成可操作的群組」。每個維度獨立評分後組合，識別出忠實客戶、潛在流失、新使用者、休眠使用者等群組。可先對照 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="說明把使用者按共同特徵分群、比較不同群組行為差異的分析方法">cohort analysis&lt;/a>（按共同特徵分群）和 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="說明追蹤使用者在多步驟流程中每一步的轉換率和流失率的分析方法">funnel analysis&lt;/a>（追蹤流程轉換率）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RFM 位在行為資料累積到一定量之後。它需要每個使用者的 session 歷史（計算 Recency 和 Frequency）和交易歷史（計算 Monetary）。免費產品可以用替代指標取代 Monetary — 產生的內容數量、邀請的使用者數、完成的關鍵操作數。RFM 的前提和 cohort analysis 相同：去識別化（&lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/redaction/" data-link-title="Redaction" data-link-desc="說明在事件資料離開 client 之前把敏感欄位的值替換成遮罩或移除的機制">redaction&lt;/a>）已完成。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>產品需要 RFM 的訊號是「需要對不同行為模式的使用者採取不同策略」。高 R 高 F 高 M 的忠實客戶需要維護關係，低 R 高 F 高 M 的潛在流失客戶需要挽留，高 R 低 F 低 M 的新使用者需要引導降低入門門檻。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>RFM 要定義每個維度的計算方式（Recency 用天數還是週數、Frequency 的時間窗口多長、Monetary 用什麼指標）、分位數（五等分還是三等分）、群組歸納（125 種 profile 歸納成幾個可操作群組）、以及重新計算的頻率（每週還是每月）。分群結果是動態的 — 使用者行為改變時群組會變。&lt;/p></description><content:encoded><![CDATA[<p>RFM 的核心概念是「用 Recency（最近活躍度）、Frequency（使用頻率）、Monetary（貢獻價值）三個維度把使用者分成可操作的群組」。每個維度獨立評分後組合，識別出忠實客戶、潛在流失、新使用者、休眠使用者等群組。可先對照 <a href="/blog/monitoring/knowledge-cards/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="說明把使用者按共同特徵分群、比較不同群組行為差異的分析方法">cohort analysis</a>（按共同特徵分群）和 <a href="/blog/monitoring/knowledge-cards/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="說明追蹤使用者在多步驟流程中每一步的轉換率和流失率的分析方法">funnel analysis</a>（追蹤流程轉換率）。</p>
<h2 id="概念位置">概念位置</h2>
<p>RFM 位在行為資料累積到一定量之後。它需要每個使用者的 session 歷史（計算 Recency 和 Frequency）和交易歷史（計算 Monetary）。免費產品可以用替代指標取代 Monetary — 產生的內容數量、邀請的使用者數、完成的關鍵操作數。RFM 的前提和 cohort analysis 相同：去識別化（<a href="/blog/monitoring/knowledge-cards/redaction/" data-link-title="Redaction" data-link-desc="說明在事件資料離開 client 之前把敏感欄位的值替換成遮罩或移除的機制">redaction</a>）已完成。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>產品需要 RFM 的訊號是「需要對不同行為模式的使用者採取不同策略」。高 R 高 F 高 M 的忠實客戶需要維護關係，低 R 高 F 高 M 的潛在流失客戶需要挽留，高 R 低 F 低 M 的新使用者需要引導降低入門門檻。</p>
<h2 id="設計責任">設計責任</h2>
<p>RFM 要定義每個維度的計算方式（Recency 用天數還是週數、Frequency 的時間窗口多長、Monetary 用什麼指標）、分位數（五等分還是三等分）、群組歸納（125 種 profile 歸納成幾個可操作群組）、以及重新計算的頻率（每週還是每月）。分群結果是動態的 — 使用者行為改變時群組會變。</p>
]]></content:encoded></item><item><title>A/B Test 的統計基礎</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/ab-test-statistics/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/ab-test-statistics/</guid><description>&lt;p>A/B test 把使用者隨機分成兩組，一組看到原版（control），一組看到改版（treatment），比較兩組的指標差異。統計方法的角色是判斷「觀察到的差異是真實的還是隨機波動」。&lt;/p>
&lt;h2 id="假設檢定">假設檢定&lt;/h2>
&lt;h3 id="虛無假設和對立假設">虛無假設和對立假設&lt;/h3>
&lt;p>虛無假設（H0）：兩組沒有差異，觀察到的差異來自隨機波動。對立假設（H1）：兩組有真實差異。&lt;/p>
&lt;p>A/B test 的邏輯是：假設 H0 成立（兩組沒有差異），計算「在 H0 成立的前提下，觀察到目前這麼大的差異的機率」。如果這個機率（p-value）很小（通常 &amp;lt; 0.05），拒絕 H0，接受 H1。&lt;/p>
&lt;h3 id="p-value-的意義">p-value 的意義&lt;/h3>
&lt;p>p-value = 0.03 代表「假設兩組沒有差異，觀察到目前差異的機率是 3%」。這個機率足夠小，合理推斷差異是真實的。&lt;/p>
&lt;p>p-value 不代表「改版比原版好的機率是 97%」。p-value 是在 H0 成立的條件下計算的，不是改版效果的機率。&lt;/p>
&lt;h3 id="兩類錯誤">兩類錯誤&lt;/h3>
&lt;p>&lt;strong>Type I error（偽陽性）&lt;/strong>：實際上沒有差異，但統計結果判定有差異。機率由顯著性水準 α 控制，通常設 0.05。&lt;/p>
&lt;p>&lt;strong>Type II error（偽陰性）&lt;/strong>：實際上有差異，但統計結果判定沒有差異。機率由統計檢定力（power = 1 - β）控制，通常要求 power ≥ 0.8。&lt;/p>
&lt;h2 id="樣本量計算">樣本量計算&lt;/h2>
&lt;p>樣本量決定了 A/B test 能偵測到多小的差異。樣本量太小，即使改版有效果，test 也沒有足夠的統計檢定力偵測到。&lt;/p>
&lt;p>樣本量計算需要四個參數：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>基準轉換率&lt;/strong>：control 組目前的轉換率（例如 5%）&lt;/li>
&lt;li>&lt;strong>最小可偵測效果（MDE）&lt;/strong>：想偵測到的最小差異（例如 5% → 6%，相對提升 20%）&lt;/li>
&lt;li>&lt;strong>顯著性水準 α&lt;/strong>：通常 0.05&lt;/li>
&lt;li>&lt;strong>統計檢定力 1 - β&lt;/strong>：通常 0.8&lt;/li>
&lt;/ul>
&lt;p>以基準轉換率 5%、MDE 相對提升 20%（5% → 6%）、α = 0.05、power = 0.8 為例，每組需要約 14,500 個樣本。如果每天有 1,000 個使用者，需要跑 29 天。&lt;/p>
&lt;p>樣本量不足時的常見錯誤是「提早看結果」— 跑了 3 天看到 p &amp;lt; 0.05 就停止。提早停止會膨脹 Type I error 率，因為隨機波動在小樣本中更容易產生看似顯著的差異。&lt;/p>
&lt;h2 id="多重比較">多重比較&lt;/h2>
&lt;p>同時跑多個 A/B test 或測試多個變體（A/B/C/D）時，整體的 Type I error 率會膨脹。&lt;/p>
&lt;p>跑 20 個 test，即使所有 test 的 H0 都成立（沒有真實差異），預期有 1 個 test（20 × 0.05）會出現 p &amp;lt; 0.05 的偽陽性。&lt;/p>
&lt;h3 id="bonferroni-校正">Bonferroni 校正&lt;/h3>
&lt;p>最簡單的校正方式：把顯著性水準除以測試數量。跑 5 個 test，每個 test 的顯著性水準改為 0.05 / 5 = 0.01。&lt;/p>
&lt;p>Bonferroni 校正很保守 — 降低了偽陽性但也降低了統計檢定力，可能錯過真實的差異。&lt;/p>
&lt;h3 id="false-discovery-ratefdr">False Discovery Rate（FDR）&lt;/h3>
&lt;p>Benjamini-Hochberg 方法控制的是「被判為顯著的結果中偽陽性的比例」，比 Bonferroni 更寬鬆。適合探索性分析（同時測試多個指標，容許一些偽陽性）。&lt;/p>
&lt;h2 id="ab-test-在自架方案的可行性">A/B test 在自架方案的可行性&lt;/h2>
&lt;p>自架 collector 可以做基礎的 A/B test 分析 — 在行為事件中記錄使用者的分組（&lt;code>variant: &amp;quot;control&amp;quot;&lt;/code> / &lt;code>variant: &amp;quot;treatment&amp;quot;&lt;/code>），計算每組的轉換率，用統計檢定比較差異。&lt;/p>
&lt;p>統計計算（p-value、信賴區間）可以用 Python（scipy.stats）或 R 完成。不需要商業 A/B test 平台。&lt;/p>
&lt;p>商業 A/B test 平台（Optimizely、LaunchDarkly、Firebase Remote Config）額外提供的是：隨機分組管理、提早停止的統計保護（sequential testing）、多變體管理的 UI、和其他分析工具的整合。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>推薦系統概論 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/recommendation-overview/" data-link-title="推薦系統概論" data-link-desc="Collaborative filtering / content-based / 混合方法 — 推薦系統的三種基本架構和各自的資料需求">推薦系統概論&lt;/a>&lt;/li>
&lt;li>使用者分群 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群&lt;/a>&lt;/li>
&lt;li>行為事件設計 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>A/B test 把使用者隨機分成兩組，一組看到原版（control），一組看到改版（treatment），比較兩組的指標差異。統計方法的角色是判斷「觀察到的差異是真實的還是隨機波動」。</p>
<h2 id="假設檢定">假設檢定</h2>
<h3 id="虛無假設和對立假設">虛無假設和對立假設</h3>
<p>虛無假設（H0）：兩組沒有差異，觀察到的差異來自隨機波動。對立假設（H1）：兩組有真實差異。</p>
<p>A/B test 的邏輯是：假設 H0 成立（兩組沒有差異），計算「在 H0 成立的前提下，觀察到目前這麼大的差異的機率」。如果這個機率（p-value）很小（通常 &lt; 0.05），拒絕 H0，接受 H1。</p>
<h3 id="p-value-的意義">p-value 的意義</h3>
<p>p-value = 0.03 代表「假設兩組沒有差異，觀察到目前差異的機率是 3%」。這個機率足夠小，合理推斷差異是真實的。</p>
<p>p-value 不代表「改版比原版好的機率是 97%」。p-value 是在 H0 成立的條件下計算的，不是改版效果的機率。</p>
<h3 id="兩類錯誤">兩類錯誤</h3>
<p><strong>Type I error（偽陽性）</strong>：實際上沒有差異，但統計結果判定有差異。機率由顯著性水準 α 控制，通常設 0.05。</p>
<p><strong>Type II error（偽陰性）</strong>：實際上有差異，但統計結果判定沒有差異。機率由統計檢定力（power = 1 - β）控制，通常要求 power ≥ 0.8。</p>
<h2 id="樣本量計算">樣本量計算</h2>
<p>樣本量決定了 A/B test 能偵測到多小的差異。樣本量太小，即使改版有效果，test 也沒有足夠的統計檢定力偵測到。</p>
<p>樣本量計算需要四個參數：</p>
<ul>
<li><strong>基準轉換率</strong>：control 組目前的轉換率（例如 5%）</li>
<li><strong>最小可偵測效果（MDE）</strong>：想偵測到的最小差異（例如 5% → 6%，相對提升 20%）</li>
<li><strong>顯著性水準 α</strong>：通常 0.05</li>
<li><strong>統計檢定力 1 - β</strong>：通常 0.8</li>
</ul>
<p>以基準轉換率 5%、MDE 相對提升 20%（5% → 6%）、α = 0.05、power = 0.8 為例，每組需要約 14,500 個樣本。如果每天有 1,000 個使用者，需要跑 29 天。</p>
<p>樣本量不足時的常見錯誤是「提早看結果」— 跑了 3 天看到 p &lt; 0.05 就停止。提早停止會膨脹 Type I error 率，因為隨機波動在小樣本中更容易產生看似顯著的差異。</p>
<h2 id="多重比較">多重比較</h2>
<p>同時跑多個 A/B test 或測試多個變體（A/B/C/D）時，整體的 Type I error 率會膨脹。</p>
<p>跑 20 個 test，即使所有 test 的 H0 都成立（沒有真實差異），預期有 1 個 test（20 × 0.05）會出現 p &lt; 0.05 的偽陽性。</p>
<h3 id="bonferroni-校正">Bonferroni 校正</h3>
<p>最簡單的校正方式：把顯著性水準除以測試數量。跑 5 個 test，每個 test 的顯著性水準改為 0.05 / 5 = 0.01。</p>
<p>Bonferroni 校正很保守 — 降低了偽陽性但也降低了統計檢定力，可能錯過真實的差異。</p>
<h3 id="false-discovery-ratefdr">False Discovery Rate（FDR）</h3>
<p>Benjamini-Hochberg 方法控制的是「被判為顯著的結果中偽陽性的比例」，比 Bonferroni 更寬鬆。適合探索性分析（同時測試多個指標，容許一些偽陽性）。</p>
<h2 id="ab-test-在自架方案的可行性">A/B test 在自架方案的可行性</h2>
<p>自架 collector 可以做基礎的 A/B test 分析 — 在行為事件中記錄使用者的分組（<code>variant: &quot;control&quot;</code> / <code>variant: &quot;treatment&quot;</code>），計算每組的轉換率，用統計檢定比較差異。</p>
<p>統計計算（p-value、信賴區間）可以用 Python（scipy.stats）或 R 完成。不需要商業 A/B test 平台。</p>
<p>商業 A/B test 平台（Optimizely、LaunchDarkly、Firebase Remote Config）額外提供的是：隨機分組管理、提早停止的統計保護（sequential testing）、多變體管理的 UI、和其他分析工具的整合。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>推薦系統概論 → <a href="/blog/monitoring/08-business-analytics/recommendation-overview/" data-link-title="推薦系統概論" data-link-desc="Collaborative filtering / content-based / 混合方法 — 推薦系統的三種基本架構和各自的資料需求">推薦系統概論</a></li>
<li>使用者分群 → <a href="/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群</a></li>
<li>行為事件設計 → <a href="/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計</a></li>
</ul>
]]></content:encoded></item><item><title>Mixpanel / Amplitude</title><link>https://tarrragon.github.io/blog/monitoring/06-commercial-comparison/mixpanel-amplitude/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/06-commercial-comparison/mixpanel-amplitude/</guid><description>&lt;p>Mixpanel 和 Amplitude 是行為分析（product analytics）專用方案。核心功能是 funnel analysis、cohort analysis、retention analysis — 回答「使用者怎麼使用產品」。和 Sentry（error-first）、Datadog（APM-first）的定位有本質差異：行為分析的消費者是產品團隊，通用監控的消費者是工程團隊。&lt;/p>
&lt;h2 id="行為分析-vs-通用監控">行為分析 vs 通用監控&lt;/h2>
&lt;p>通用監控方案（Sentry、Crashlytics、Datadog）的主要產出是 error 報告和 performance 數據 — 工程團隊用來修復 bug 和優化效能。&lt;/p>
&lt;p>行為分析方案的主要產出是 funnel 和 cohort 數據 — 產品團隊用來決定功能優先順序、評估改版效果、優化使用者體驗。&lt;/p>
&lt;p>兩類需求可以共存。工程團隊需要 error tracking，產品團隊需要行為分析。一些團隊同時使用 Sentry + Mixpanel，各自服務不同的消費者。&lt;/p>
&lt;h2 id="核心功能">核心功能&lt;/h2>
&lt;h3 id="funnel-analysis">Funnel analysis&lt;/h3>
&lt;p>定義使用者操作的步驟序列，計算每步的轉換率和流失率。Mixpanel 和 Amplitude 的 funnel 分析支援：步驟之間的時間窗口限制（步驟 1 到步驟 2 在 24 小時內完成才算轉換）、按使用者屬性分群（新使用者 vs 老使用者的轉換率差異）、步驟之間的路徑分析（流失的使用者去了哪裡）。&lt;/p>
&lt;p>自架方案能做基礎的 funnel 計數（&lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/" data-link-title="模組八：行為資料的商業利用" data-link-desc="Funnel / Cohort / Attribution / A/B test / 推薦系統 / RFM — 從 debug 工具到商業資產的翻轉">模組八 自架 funnel&lt;/a>），但不支援時間窗口、分群和路徑分析。&lt;/p>
&lt;h3 id="cohort-analysis">Cohort analysis&lt;/h3>
&lt;p>按使用者屬性或行為把使用者分成群組，比較不同群組的行為差異。例：「從 Google 廣告來的使用者」vs「從社群分享來的使用者」，兩組的留存率和付費率差異。&lt;/p>
&lt;h3 id="retention-analysis">Retention analysis&lt;/h3>
&lt;p>追蹤使用者在初次使用後的回訪率。Day 1 / Day 7 / Day 30 retention — 多少使用者在首次使用後 1 天 / 7 天 / 30 天內回來。&lt;/p>
&lt;p>Retention 是產品健康度的核心指標。行為分析方案提供 retention curve（留存曲線）和 retention by cohort（不同群組的留存差異），這些在自架方案中需要大量的 SQL 查詢和手動計算。&lt;/p>
&lt;h2 id="mixpanel-vs-amplitude-的差異">Mixpanel vs Amplitude 的差異&lt;/h2>
&lt;p>兩者的功能高度重疊，差異主要在定價和資料模型：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>Mixpanel&lt;/th>
 &lt;th>Amplitude&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>定價模型&lt;/td>
 &lt;td>按事件量計費&lt;/td>
 &lt;td>按 MTU（月活使用者）計費&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料模型&lt;/td>
 &lt;td>event-centric（事件為中心）&lt;/td>
 &lt;td>event + user profile&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SQL 查詢&lt;/td>
 &lt;td>JQL（自訂查詢語言）&lt;/td>
 &lt;td>原生 SQL 支援（Amplitude SQL）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>免費額度&lt;/td>
 &lt;td>每月 2000 萬事件&lt;/td>
 &lt;td>每月 1000 萬事件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>整合&lt;/td>
 &lt;td>豐富的第三方整合&lt;/td>
 &lt;td>CDP（Customer Data Platform）強&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>選擇依據通常是團隊的既有工具鏈和定價模型偏好。&lt;/p>
&lt;h2 id="什麼時候需要行為分析方案">什麼時候需要行為分析方案&lt;/h2>
&lt;p>行為分析方案的投資在以下條件下有回報：&lt;/p>
&lt;p>&lt;strong>有產品團隊消費數據&lt;/strong>：如果只有工程團隊，error tracking + 自架 log 通常足夠。行為分析方案的 dashboard 需要產品團隊定期查看和基於數據做決策。&lt;/p>
&lt;p>&lt;strong>使用者數量足夠產生統計意義&lt;/strong>：Funnel 和 cohort 分析需要足夠的樣本量。DAU &amp;lt; 100 的產品，分析結果的統計信度低。&lt;/p>
&lt;p>&lt;strong>有明確的優化目標&lt;/strong>：「提高註冊轉換率」「降低 Day 7 流失率」— 有具體的 metric 目標，行為分析方案能提供追蹤和歸因。&lt;/p>
&lt;p>自用工具場景下不需要行為分析方案 — 使用者就是開發者本人，行為數據沒有分析價值。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>自架 vs 商業的判斷 → &lt;a href="https://tarrragon.github.io/blog/monitoring/06-commercial-comparison/self-hosted-vs-commercial/" data-link-title="自架 vs 商業的判斷決策表" data-link-desc="使用者數、網路範圍、功能需求、合規要求四個維度判斷該自架還是用商業方案">自架 vs 商業的判斷決策表&lt;/a>&lt;/li>
&lt;li>行為分析的方法論 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/" data-link-title="模組八：行為資料的商業利用" data-link-desc="Funnel / Cohort / Attribution / A/B test / 推薦系統 / RFM — 從 debug 工具到商業資產的翻轉">模組八 行為資料的商業利用&lt;/a>&lt;/li>
&lt;li>四類事件在商業方案中的對應 → &lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/commercial-event-mapping/" data-link-title="商業方案的事件類型對應" data-link-desc="Sentry / Crashlytics / GA4 / Datadog RUM 各自如何對應四類事件 — 理解商業方案的分類邏輯才能正確接入">模組一 商業方案事件類型對應&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Mixpanel 和 Amplitude 是行為分析（product analytics）專用方案。核心功能是 funnel analysis、cohort analysis、retention analysis — 回答「使用者怎麼使用產品」。和 Sentry（error-first）、Datadog（APM-first）的定位有本質差異：行為分析的消費者是產品團隊，通用監控的消費者是工程團隊。</p>
<h2 id="行為分析-vs-通用監控">行為分析 vs 通用監控</h2>
<p>通用監控方案（Sentry、Crashlytics、Datadog）的主要產出是 error 報告和 performance 數據 — 工程團隊用來修復 bug 和優化效能。</p>
<p>行為分析方案的主要產出是 funnel 和 cohort 數據 — 產品團隊用來決定功能優先順序、評估改版效果、優化使用者體驗。</p>
<p>兩類需求可以共存。工程團隊需要 error tracking，產品團隊需要行為分析。一些團隊同時使用 Sentry + Mixpanel，各自服務不同的消費者。</p>
<h2 id="核心功能">核心功能</h2>
<h3 id="funnel-analysis">Funnel analysis</h3>
<p>定義使用者操作的步驟序列，計算每步的轉換率和流失率。Mixpanel 和 Amplitude 的 funnel 分析支援：步驟之間的時間窗口限制（步驟 1 到步驟 2 在 24 小時內完成才算轉換）、按使用者屬性分群（新使用者 vs 老使用者的轉換率差異）、步驟之間的路徑分析（流失的使用者去了哪裡）。</p>
<p>自架方案能做基礎的 funnel 計數（<a href="/blog/monitoring/08-business-analytics/" data-link-title="模組八：行為資料的商業利用" data-link-desc="Funnel / Cohort / Attribution / A/B test / 推薦系統 / RFM — 從 debug 工具到商業資產的翻轉">模組八 自架 funnel</a>），但不支援時間窗口、分群和路徑分析。</p>
<h3 id="cohort-analysis">Cohort analysis</h3>
<p>按使用者屬性或行為把使用者分成群組，比較不同群組的行為差異。例：「從 Google 廣告來的使用者」vs「從社群分享來的使用者」，兩組的留存率和付費率差異。</p>
<h3 id="retention-analysis">Retention analysis</h3>
<p>追蹤使用者在初次使用後的回訪率。Day 1 / Day 7 / Day 30 retention — 多少使用者在首次使用後 1 天 / 7 天 / 30 天內回來。</p>
<p>Retention 是產品健康度的核心指標。行為分析方案提供 retention curve（留存曲線）和 retention by cohort（不同群組的留存差異），這些在自架方案中需要大量的 SQL 查詢和手動計算。</p>
<h2 id="mixpanel-vs-amplitude-的差異">Mixpanel vs Amplitude 的差異</h2>
<p>兩者的功能高度重疊，差異主要在定價和資料模型：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Mixpanel</th>
          <th>Amplitude</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>定價模型</td>
          <td>按事件量計費</td>
          <td>按 MTU（月活使用者）計費</td>
      </tr>
      <tr>
          <td>資料模型</td>
          <td>event-centric（事件為中心）</td>
          <td>event + user profile</td>
      </tr>
      <tr>
          <td>SQL 查詢</td>
          <td>JQL（自訂查詢語言）</td>
          <td>原生 SQL 支援（Amplitude SQL）</td>
      </tr>
      <tr>
          <td>免費額度</td>
          <td>每月 2000 萬事件</td>
          <td>每月 1000 萬事件</td>
      </tr>
      <tr>
          <td>整合</td>
          <td>豐富的第三方整合</td>
          <td>CDP（Customer Data Platform）強</td>
      </tr>
  </tbody>
</table>
<p>選擇依據通常是團隊的既有工具鏈和定價模型偏好。</p>
<h2 id="什麼時候需要行為分析方案">什麼時候需要行為分析方案</h2>
<p>行為分析方案的投資在以下條件下有回報：</p>
<p><strong>有產品團隊消費數據</strong>：如果只有工程團隊，error tracking + 自架 log 通常足夠。行為分析方案的 dashboard 需要產品團隊定期查看和基於數據做決策。</p>
<p><strong>使用者數量足夠產生統計意義</strong>：Funnel 和 cohort 分析需要足夠的樣本量。DAU &lt; 100 的產品，分析結果的統計信度低。</p>
<p><strong>有明確的優化目標</strong>：「提高註冊轉換率」「降低 Day 7 流失率」— 有具體的 metric 目標，行為分析方案能提供追蹤和歸因。</p>
<p>自用工具場景下不需要行為分析方案 — 使用者就是開發者本人，行為數據沒有分析價值。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>自架 vs 商業的判斷 → <a href="/blog/monitoring/06-commercial-comparison/self-hosted-vs-commercial/" data-link-title="自架 vs 商業的判斷決策表" data-link-desc="使用者數、網路範圍、功能需求、合規要求四個維度判斷該自架還是用商業方案">自架 vs 商業的判斷決策表</a></li>
<li>行為分析的方法論 → <a href="/blog/monitoring/08-business-analytics/" data-link-title="模組八：行為資料的商業利用" data-link-desc="Funnel / Cohort / Attribution / A/B test / 推薦系統 / RFM — 從 debug 工具到商業資產的翻轉">模組八 行為資料的商業利用</a></li>
<li>四類事件在商業方案中的對應 → <a href="/blog/monitoring/01-mental-model/commercial-event-mapping/" data-link-title="商業方案的事件類型對應" data-link-desc="Sentry / Crashlytics / GA4 / Datadog RUM 各自如何對應四類事件 — 理解商業方案的分類邏輯才能正確接入">模組一 商業方案事件類型對應</a></li>
</ul>
]]></content:encoded></item><item><title>動機驅動的事件設計</title><link>https://tarrragon.github.io/blog/monitoring/01-mental-model/motivation-to-event-mapping/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/01-mental-model/motivation-to-event-mapping/</guid><description>&lt;p>事件設計是三維結構：動機（為什麼收）決定需要什麼事件、感測器（怎麼收）決定在前端哪裡埋點、生命週期（什麼時候收）決定各事件在哪個產品階段啟用。本章展開&lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/derive-collection-from-requirements/" data-link-title="從需求推導「該收集哪些事件」" data-link-desc="從 debug 需求、行為分析需求、效能需求、合規需求四個方向推導事件收集策略 — 避免「什麼都收」和「什麼都不收」">從需求推導收集策略&lt;/a>的四個方向到具體事件名稱級。從動機出發反推事件清單，比從技術能力出發（「SDK 能收什麼就收什麼」）更精準 — 每個事件都能回指一個具體的消費場景。&lt;/p>
&lt;h2 id="debug-動機">Debug 動機&lt;/h2>
&lt;p>Debug 動機驅動的事件收集目標是「問題發生時、開發者能從事件記錄中重建 context 並定位根因」。&lt;/p>
&lt;h3 id="要偵測的行為">要偵測的行為&lt;/h3>
&lt;ul>
&lt;li>多步驟流程的每一步完成或失敗（連線 → 認證 → 資料交換）&lt;/li>
&lt;li>系統狀態轉換（前景/背景、連線/斷線、登入/登出）&lt;/li>
&lt;li>非預期例外（uncaught exception、network error、timeout）&lt;/li>
&lt;li>使用者最近的操作序列（問題發生前做了什麼）&lt;/li>
&lt;/ul>
&lt;h3 id="事件表">事件表&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>事件名稱&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>觸發時機&lt;/th>
 &lt;th>data schema 重點&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>{feature}.step.done&lt;/td>
 &lt;td>lifecycle&lt;/td>
 &lt;td>流程步驟完成&lt;/td>
 &lt;td>step_name, duration_ms&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>{feature}.step.failed&lt;/td>
 &lt;td>error&lt;/td>
 &lt;td>流程步驟失敗&lt;/td>
 &lt;td>step_name, error, context&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>app.exception&lt;/td>
 &lt;td>error&lt;/td>
 &lt;td>uncaught exception&lt;/td>
 &lt;td>message, stack_trace, component&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>ws.connected / ws.disconnected&lt;/td>
 &lt;td>lifecycle&lt;/td>
 &lt;td>連線狀態變化&lt;/td>
 &lt;td>url, reason, code&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>app.foreground / app.background&lt;/td>
 &lt;td>lifecycle&lt;/td>
 &lt;td>app 前後景切換&lt;/td>
 &lt;td>duration_in_background&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>{action}.completed&lt;/td>
 &lt;td>event&lt;/td>
 &lt;td>使用者完成操作&lt;/td>
 &lt;td>action_detail&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="查詢場景">查詢場景&lt;/h3>
&lt;p>&lt;strong>Session 回放&lt;/strong>：按 session_id 過濾、按時間排序，還原「使用者做了什麼 → 系統發生了什麼 → 問題在哪裡出現」。&lt;/p>
&lt;p>&lt;strong>Error 根因定位&lt;/strong>：按 error name GROUP BY，找出最常出現的錯誤。單筆 error 的 stack_trace + 同 session 的 lifecycle 事件組合，判斷失敗發生在流程的哪一步。&lt;/p>
&lt;p>&lt;strong>最近 N 個操作&lt;/strong>：error 發生前的 10-20 個 event/lifecycle 事件，等同 Sentry 的 breadcrumb trail。&lt;/p>
&lt;h3 id="生命週期階段">生命週期階段&lt;/h3>
&lt;p>開發期起全開。Debug 事件是最早需要的 — 實機測試階段就依賴這些事件定位問題。error 類和 lifecycle 類不做取樣（量低且每筆都可能是線索）。&lt;/p>
&lt;h2 id="商業動機">商業動機&lt;/h2>
&lt;p>商業動機驅動的事件收集目標是「回答產品決策的問題 — 使用者在哪裡流失、不同群組行為有什麼差異、哪些功能被使用」。&lt;/p>
&lt;h3 id="要偵測的行為-1">要偵測的行為&lt;/h3>
&lt;ul>
&lt;li>漏斗步驟完成（註冊 → 啟用 → 付費 → 續約的每一步）&lt;/li>
&lt;li>功能使用頻率（哪些功能被頻繁使用、哪些從未被觸發）&lt;/li>
&lt;li>Session 長度和頻率（使用者多常用、每次用多久）&lt;/li>
&lt;li>關鍵轉換事件（首次付費、邀請好友、升級方案）&lt;/li>
&lt;/ul>
&lt;h3 id="事件表-1">事件表&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>事件名稱&lt;/th>
 &lt;th>類型&lt;/th>
 &lt;th>觸發時機&lt;/th>
 &lt;th>data schema 重點&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>funnel.{name}.step_N&lt;/td>
 &lt;td>event&lt;/td>
 &lt;td>漏斗步驟完成&lt;/td>
 &lt;td>step_name, funnel_name&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>feature.{name}.used&lt;/td>
 &lt;td>event&lt;/td>
 &lt;td>使用者使用特定功能&lt;/td>
 &lt;td>feature_name, context&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>session.start / session.end&lt;/td>
 &lt;td>lifecycle&lt;/td>
 &lt;td>session 邊界&lt;/td>
 &lt;td>session_duration&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>conversion.{type}&lt;/td>
 &lt;td>event&lt;/td>
 &lt;td>關鍵轉換&lt;/td>
 &lt;td>conversion_type, value&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="查詢場景-1">查詢場景&lt;/h3>
&lt;p>&lt;strong>Funnel 轉換率&lt;/strong>：每步的完成數 / 上一步的完成數。SQLite 層做每步計數，PostgreSQL 層做 session 級 JOIN 的精確轉換率（見 &lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇&lt;/a>）。&lt;/p>
&lt;p>&lt;strong>Cohort 留存&lt;/strong>：按「首次使用週」分群，計算每週的回訪率。需要 session.start 事件 + 使用者首次出現的時間戳。&lt;/p>
&lt;p>&lt;strong>功能使用率&lt;/strong>：feature.*.used 事件按 name GROUP BY COUNT，排序找出最常/最少使用的功能。&lt;/p>
&lt;h3 id="生命週期階段-1">生命週期階段&lt;/h3>
&lt;p>上線後啟用。開發期不需要商業事件（沒有真實使用者）。測試期可以用模擬流量驗證 funnel 事件的觸發正確性，但不做分析。&lt;/p>
&lt;h2 id="資安動機">資安動機&lt;/h2>
&lt;p>資安動機驅動的事件收集目標是「偵測非預期的存取模式、追蹤敏感操作、提供事後稽核的 audit trail」。&lt;/p></description><content:encoded><![CDATA[<p>事件設計是三維結構：動機（為什麼收）決定需要什麼事件、感測器（怎麼收）決定在前端哪裡埋點、生命週期（什麼時候收）決定各事件在哪個產品階段啟用。本章展開<a href="/blog/monitoring/01-mental-model/derive-collection-from-requirements/" data-link-title="從需求推導「該收集哪些事件」" data-link-desc="從 debug 需求、行為分析需求、效能需求、合規需求四個方向推導事件收集策略 — 避免「什麼都收」和「什麼都不收」">從需求推導收集策略</a>的四個方向到具體事件名稱級。從動機出發反推事件清單，比從技術能力出發（「SDK 能收什麼就收什麼」）更精準 — 每個事件都能回指一個具體的消費場景。</p>
<h2 id="debug-動機">Debug 動機</h2>
<p>Debug 動機驅動的事件收集目標是「問題發生時、開發者能從事件記錄中重建 context 並定位根因」。</p>
<h3 id="要偵測的行為">要偵測的行為</h3>
<ul>
<li>多步驟流程的每一步完成或失敗（連線 → 認證 → 資料交換）</li>
<li>系統狀態轉換（前景/背景、連線/斷線、登入/登出）</li>
<li>非預期例外（uncaught exception、network error、timeout）</li>
<li>使用者最近的操作序列（問題發生前做了什麼）</li>
</ul>
<h3 id="事件表">事件表</h3>
<table>
  <thead>
      <tr>
          <th>事件名稱</th>
          <th>類型</th>
          <th>觸發時機</th>
          <th>data schema 重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>{feature}.step.done</td>
          <td>lifecycle</td>
          <td>流程步驟完成</td>
          <td>step_name, duration_ms</td>
      </tr>
      <tr>
          <td>{feature}.step.failed</td>
          <td>error</td>
          <td>流程步驟失敗</td>
          <td>step_name, error, context</td>
      </tr>
      <tr>
          <td>app.exception</td>
          <td>error</td>
          <td>uncaught exception</td>
          <td>message, stack_trace, component</td>
      </tr>
      <tr>
          <td>ws.connected / ws.disconnected</td>
          <td>lifecycle</td>
          <td>連線狀態變化</td>
          <td>url, reason, code</td>
      </tr>
      <tr>
          <td>app.foreground / app.background</td>
          <td>lifecycle</td>
          <td>app 前後景切換</td>
          <td>duration_in_background</td>
      </tr>
      <tr>
          <td>{action}.completed</td>
          <td>event</td>
          <td>使用者完成操作</td>
          <td>action_detail</td>
      </tr>
  </tbody>
</table>
<h3 id="查詢場景">查詢場景</h3>
<p><strong>Session 回放</strong>：按 session_id 過濾、按時間排序，還原「使用者做了什麼 → 系統發生了什麼 → 問題在哪裡出現」。</p>
<p><strong>Error 根因定位</strong>：按 error name GROUP BY，找出最常出現的錯誤。單筆 error 的 stack_trace + 同 session 的 lifecycle 事件組合，判斷失敗發生在流程的哪一步。</p>
<p><strong>最近 N 個操作</strong>：error 發生前的 10-20 個 event/lifecycle 事件，等同 Sentry 的 breadcrumb trail。</p>
<h3 id="生命週期階段">生命週期階段</h3>
<p>開發期起全開。Debug 事件是最早需要的 — 實機測試階段就依賴這些事件定位問題。error 類和 lifecycle 類不做取樣（量低且每筆都可能是線索）。</p>
<h2 id="商業動機">商業動機</h2>
<p>商業動機驅動的事件收集目標是「回答產品決策的問題 — 使用者在哪裡流失、不同群組行為有什麼差異、哪些功能被使用」。</p>
<h3 id="要偵測的行為-1">要偵測的行為</h3>
<ul>
<li>漏斗步驟完成（註冊 → 啟用 → 付費 → 續約的每一步）</li>
<li>功能使用頻率（哪些功能被頻繁使用、哪些從未被觸發）</li>
<li>Session 長度和頻率（使用者多常用、每次用多久）</li>
<li>關鍵轉換事件（首次付費、邀請好友、升級方案）</li>
</ul>
<h3 id="事件表-1">事件表</h3>
<table>
  <thead>
      <tr>
          <th>事件名稱</th>
          <th>類型</th>
          <th>觸發時機</th>
          <th>data schema 重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>funnel.{name}.step_N</td>
          <td>event</td>
          <td>漏斗步驟完成</td>
          <td>step_name, funnel_name</td>
      </tr>
      <tr>
          <td>feature.{name}.used</td>
          <td>event</td>
          <td>使用者使用特定功能</td>
          <td>feature_name, context</td>
      </tr>
      <tr>
          <td>session.start / session.end</td>
          <td>lifecycle</td>
          <td>session 邊界</td>
          <td>session_duration</td>
      </tr>
      <tr>
          <td>conversion.{type}</td>
          <td>event</td>
          <td>關鍵轉換</td>
          <td>conversion_type, value</td>
      </tr>
  </tbody>
</table>
<h3 id="查詢場景-1">查詢場景</h3>
<p><strong>Funnel 轉換率</strong>：每步的完成數 / 上一步的完成數。SQLite 層做每步計數，PostgreSQL 層做 session 級 JOIN 的精確轉換率（見 <a href="/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇</a>）。</p>
<p><strong>Cohort 留存</strong>：按「首次使用週」分群，計算每週的回訪率。需要 session.start 事件 + 使用者首次出現的時間戳。</p>
<p><strong>功能使用率</strong>：feature.*.used 事件按 name GROUP BY COUNT，排序找出最常/最少使用的功能。</p>
<h3 id="生命週期階段-1">生命週期階段</h3>
<p>上線後啟用。開發期不需要商業事件（沒有真實使用者）。測試期可以用模擬流量驗證 funnel 事件的觸發正確性，但不做分析。</p>
<h2 id="資安動機">資安動機</h2>
<p>資安動機驅動的事件收集目標是「偵測非預期的存取模式、追蹤敏感操作、提供事後稽核的 audit trail」。</p>
<h3 id="要偵測的行為-2">要偵測的行為</h3>
<ul>
<li>認證失敗（密碼錯誤、biometric 失敗、token 過期）</li>
<li>權限越界嘗試（嘗試存取非自己的資源、呼叫無權限的 API）</li>
<li>敏感資料存取（查看個資、匯出資料、修改權限設定）</li>
<li>異常存取模式（短時間大量請求、非常規時段存取、來源 IP 變化）</li>
</ul>
<h3 id="事件表-2">事件表</h3>
<table>
  <thead>
      <tr>
          <th>事件名稱</th>
          <th>類型</th>
          <th>觸發時機</th>
          <th>data schema 重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>auth.{method}.failed</td>
          <td>error</td>
          <td>認證失敗</td>
          <td>method, failure_reason, attempt_count</td>
      </tr>
      <tr>
          <td>auth.{method}.success</td>
          <td>event</td>
          <td>認證成功（語意上是系統回呼、歸為 event 是業界慣例）</td>
          <td>method, duration_ms</td>
      </tr>
      <tr>
          <td>authz.denied</td>
          <td>error</td>
          <td>權限檢查拒絕</td>
          <td>resource, action, role</td>
      </tr>
      <tr>
          <td>sensitive.accessed</td>
          <td>event</td>
          <td>敏感資料被存取</td>
          <td>resource_type, accessor_role</td>
      </tr>
      <tr>
          <td>sensitive.exported</td>
          <td>event</td>
          <td>資料被匯出</td>
          <td>export_format, record_count</td>
      </tr>
      <tr>
          <td>admin.setting.changed</td>
          <td>event</td>
          <td>管理設定變更</td>
          <td>setting_key, old_value_hash, new_value_hash</td>
      </tr>
  </tbody>
</table>
<h3 id="查詢場景-2">查詢場景</h3>
<p><strong>認證失敗監控</strong>：auth.*.failed 事件的 count by session_id，短時間內同一 session 多次失敗 → 暴力破解嫌疑。Rule engine 設閾值告警。</p>
<p><strong>Audit trail</strong>：sensitive.* 和 admin.* 事件按時間排列，回答「誰在什麼時候存取/修改了什麼」。合規審計的必要紀錄。</p>
<p><strong>異常 pattern 偵測</strong>：auth 成功後的操作事件頻率和模式分析。正常使用者每 session 操作 10-50 次；自動化腳本可能操作數千次。</p>
<h3 id="生命週期階段-2">生命週期階段</h3>
<p>開發期起全開。安全事件不能延後 — 「先不收安全事件、上線後再加」等於安全審計的空白期。認證相關事件是 auto-intercept 的一部分（見 <a href="/blog/monitoring/03-sdk-design/auto-intercept/" data-link-title="自動攔截機制" data-link-desc="JS window.onerror / Flutter FlutterError.onError / Python sys.excepthook — 各平台攔截未捕獲例外的機制和限制">自動攔截機制</a>），不需要手動埋點。</p>
<h3 id="和-redaction-的關係">和 redaction 的關係</h3>
<p>資安事件本身可能包含敏感資訊（失敗的密碼、被存取的個資欄位名稱）。事件的 data schema 設計時標記需要 <a href="/blog/monitoring/knowledge-cards/redaction/" data-link-title="Redaction" data-link-desc="說明在事件資料離開 client 之前把敏感欄位的值替換成遮罩或移除的機制">redaction</a> 的欄位 — auth.failed 記錄失敗原因但不記錄輸入的密碼、sensitive.accessed 記錄資源類型但不記錄資源內容。</p>
<h2 id="效能動機">效能動機</h2>
<p>效能動機驅動的事件收集目標是「發現效能退化趨勢、定位效能瓶頸、為容量規劃提供數據」。</p>
<h3 id="要偵測的行為-3">要偵測的行為</h3>
<ul>
<li>操作回應時間（API 呼叫、頁面載入、動畫轉場）</li>
<li>渲染效能（frame rate、長任務、佈局重排）</li>
<li>資源使用（記憶體、CPU、網路流量）</li>
<li>外部依賴延遲（第三方 API、CDN、資料庫查詢）</li>
</ul>
<h3 id="事件表-3">事件表</h3>
<table>
  <thead>
      <tr>
          <th>事件名稱</th>
          <th>類型</th>
          <th>觸發時機</th>
          <th>data schema 重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>{operation}.duration</td>
          <td>metric</td>
          <td>操作完成</td>
          <td>duration_ms, operation_name</td>
      </tr>
      <tr>
          <td>render.frame_drop</td>
          <td>metric</td>
          <td>掉幀偵測</td>
          <td>dropped_frames, total_frames</td>
      </tr>
      <tr>
          <td>resource.memory</td>
          <td>metric</td>
          <td>定期取樣（30s）</td>
          <td>heap_used, heap_total</td>
      </tr>
      <tr>
          <td>dependency.{name}.latency</td>
          <td>metric</td>
          <td>外部呼叫完成</td>
          <td>dependency_name, latency_ms, status</td>
      </tr>
      <tr>
          <td>web.vitals</td>
          <td>metric</td>
          <td>Web 頁面載入</td>
          <td>lcp_ms, fid_ms, cls_score</td>
      </tr>
  </tbody>
</table>
<h3 id="查詢場景-3">查詢場景</h3>
<p><strong>P95 趨勢</strong>：{operation}.duration 事件按天聚合、計算 percentile_cont(0.95)，觀察回應時間是否隨版本增加。</p>
<p><strong>容量規劃</strong>：resource.memory 事件的趨勢圖，判斷記憶體是否隨使用時間穩定增長（memory leak 訊號）。</p>
<p><strong>依賴健康度</strong>：dependency.*.latency 事件按 dependency_name GROUP BY，比較各依賴的平均延遲和失敗率。</p>
<h3 id="生命週期階段-3">生命週期階段</h3>
<p>測試期起啟用。開發期不需要效能事件（本地環境的效能數據不代表 production）。測試期啟用用於建立效能 baseline。上線後持續收集用於趨勢監控。</p>
<p>效能事件量通常最大（每 30 秒一筆 resource.memory × 活躍使用者數），取樣率需要控制 — 自用場景全收、商業產品取樣 10-50%（見 <a href="/blog/monitoring/03-sdk-design/frontend-sensor-design/" data-link-title="前端感測器設計" data-link-desc="什麼行為值得埋感測器、每類感測器的實作方式、取樣策略和效能影響 — 和 auto-intercept 的被動攔截互補">前端感測器設計</a> 的取樣策略段）。</p>
<h2 id="ab-測試動機">A/B 測試動機</h2>
<p>A/B 測試動機驅動的事件是商業動機的延伸 — 實驗期間收集實驗分組和轉換事件，實驗結束後關閉。</p>
<h3 id="事件表-4">事件表</h3>
<table>
  <thead>
      <tr>
          <th>事件名稱</th>
          <th>類型</th>
          <th>觸發時機</th>
          <th>data schema 重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>experiment.{name}.assigned</td>
          <td>event</td>
          <td>使用者被分配到實驗組</td>
          <td>experiment_name, variant</td>
      </tr>
      <tr>
          <td>experiment.{name}.converted</td>
          <td>event</td>
          <td>使用者完成轉換目標</td>
          <td>experiment_name, variant, conversion_type</td>
      </tr>
  </tbody>
</table>
<h3 id="生命週期階段-4">生命週期階段</h3>
<p>實驗期間啟用，實驗結束後關閉（從 SDK config 或 feature flag 移除）。實驗事件的保留期限跟著實驗週期走 — 實驗結束 + 分析完成後可清除。A/B test 的統計分析見 <a href="/blog/monitoring/08-business-analytics/ab-test-statistics/" data-link-title="A/B Test 的統計基礎" data-link-desc="假設檢定、樣本量計算、多重比較校正 — A/B test 不只是「比較兩個數字」，統計方法決定結論是否可靠">A/B test 的統計基礎</a>。</p>
<h2 id="完整對照總表">完整對照總表</h2>
<table>
  <thead>
      <tr>
          <th>動機</th>
          <th>要偵測的行為</th>
          <th>事件名稱模式</th>
          <th>感測器類型</th>
          <th>生命週期啟用</th>
          <th>查詢模式</th>
          <th>保留層級</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Debug</td>
          <td>流程步驟完成/失敗</td>
          <td>{feature}.step.*</td>
          <td>auto-intercept</td>
          <td>開發期起</td>
          <td>session 回放</td>
          <td>原始 7d</td>
      </tr>
      <tr>
          <td>Debug</td>
          <td>例外拋出</td>
          <td>app.exception</td>
          <td>auto-intercept</td>
          <td>開發期起</td>
          <td>error GROUP BY</td>
          <td>原始 30d</td>
      </tr>
      <tr>
          <td>Debug</td>
          <td>連線狀態</td>
          <td>ws.connected/disconnected</td>
          <td>auto-intercept</td>
          <td>開發期起</td>
          <td>session 回放</td>
          <td>原始 7d</td>
      </tr>
      <tr>
          <td>Debug</td>
          <td>最近操作</td>
          <td>{action}.completed</td>
          <td>手動埋點</td>
          <td>開發期起</td>
          <td>breadcrumb trail</td>
          <td>原始 7d</td>
      </tr>
      <tr>
          <td>商業</td>
          <td>漏斗步驟</td>
          <td>funnel.{name}.step_N</td>
          <td>手動埋點</td>
          <td>上線後</td>
          <td>funnel JOIN</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>商業</td>
          <td>功能使用</td>
          <td>feature.{name}.used</td>
          <td>手動埋點</td>
          <td>上線後</td>
          <td>COUNT GROUP BY</td>
          <td>天聚合 365d</td>
      </tr>
      <tr>
          <td>商業</td>
          <td>Session</td>
          <td>session.start/end</td>
          <td>auto-intercept</td>
          <td>上線後</td>
          <td>cohort 留存</td>
          <td>天聚合 365d</td>
      </tr>
      <tr>
          <td>商業</td>
          <td>轉換</td>
          <td>conversion.{type}</td>
          <td>手動埋點</td>
          <td>上線後</td>
          <td>funnel 最後一步</td>
          <td>原始 90d</td>
      </tr>
      <tr>
          <td>資安</td>
          <td>認證失敗</td>
          <td>auth.{method}.failed</td>
          <td>auto-intercept</td>
          <td>開發期起</td>
          <td>閾值告警</td>
          <td>原始 30d</td>
      </tr>
      <tr>
          <td>資安</td>
          <td>權限拒絕</td>
          <td>authz.denied</td>
          <td>auto-intercept</td>
          <td>開發期起</td>
          <td>pattern 偵測</td>
          <td>原始 30d</td>
      </tr>
      <tr>
          <td>資安</td>
          <td>敏感存取</td>
          <td>sensitive.*</td>
          <td>手動埋點</td>
          <td>開發期起</td>
          <td>audit trail</td>
          <td>原始 365d</td>
      </tr>
      <tr>
          <td>資安</td>
          <td>設定變更</td>
          <td>admin.setting.changed</td>
          <td>手動埋點</td>
          <td>開發期起</td>
          <td>audit trail</td>
          <td>原始 365d</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>操作延遲</td>
          <td>{operation}.duration</td>
          <td>手動埋點</td>
          <td>測試期起</td>
          <td>P95 趨勢</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>渲染效能</td>
          <td>render.frame_drop</td>
          <td>auto-intercept</td>
          <td>測試期起</td>
          <td>趨勢圖</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>資源用量</td>
          <td>resource.memory</td>
          <td>定期取樣</td>
          <td>測試期起</td>
          <td>趨勢圖</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>外部依賴</td>
          <td>dependency.{name}.latency</td>
          <td>手動埋點</td>
          <td>測試期起</td>
          <td>GROUP BY 依賴</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>Web Vitals</td>
          <td>web.vitals</td>
          <td>auto-intercept</td>
          <td>測試期起</td>
          <td>趨勢圖</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>A/B</td>
          <td>實驗分組</td>
          <td>experiment.{name}.assigned</td>
          <td>手動埋點</td>
          <td>實驗期間</td>
          <td>variant GROUP BY</td>
          <td>實驗結束後清</td>
      </tr>
      <tr>
          <td>A/B</td>
          <td>實驗轉換</td>
          <td>experiment.{name}.converted</td>
          <td>手動埋點</td>
          <td>實驗期間</td>
          <td>轉換率計算</td>
          <td>實驗結束後清</td>
      </tr>
      <tr>
          <td>DevOps</td>
          <td>Collector 存活</td>
          <td>collector.health.check</td>
          <td>Collector 內部</td>
          <td>開發期起</td>
          <td>狀態卡</td>
          <td>原始 7d</td>
      </tr>
      <tr>
          <td>DevOps</td>
          <td>事件吞吐量</td>
          <td>collector.ingestion.count</td>
          <td>Collector 內部</td>
          <td>開發期起</td>
          <td>吞吐曲線</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>DevOps</td>
          <td>儲存用量</td>
          <td>collector.storage.disk_usage</td>
          <td>Collector 內部</td>
          <td>開發期起</td>
          <td>儲存圖</td>
          <td>小時聚合 90d</td>
      </tr>
      <tr>
          <td>DevOps</td>
          <td>SDK 心跳</td>
          <td>sdk.heartbeat</td>
          <td>SDK 端</td>
          <td>開發期起</td>
          <td>連線列表</td>
          <td>原始 7d</td>
      </tr>
      <tr>
          <td>DevOps</td>
          <td>部署事件</td>
          <td>deployment.completed</td>
          <td>CI/CD hook</td>
          <td>開發期起</td>
          <td>部署狀態</td>
          <td>原始 30d</td>
      </tr>
      <tr>
          <td>DevOps</td>
          <td>規則命中</td>
          <td>rule.matched</td>
          <td>Collector 內部</td>
          <td>開發期起</td>
          <td>alert 歷史</td>
          <td>原始 30d</td>
      </tr>
      <tr>
          <td>中台</td>
          <td>使用者首次出現</td>
          <td>user.first_seen</td>
          <td>Collector 計算</td>
          <td>上線後</td>
          <td>cohort 分群</td>
          <td>天聚合 365d</td>
      </tr>
      <tr>
          <td>中台</td>
          <td>通路歸因</td>
          <td>attribution.install_source</td>
          <td>SDK 首次啟動</td>
          <td>上線後</td>
          <td>歸因報表</td>
          <td>原始 90d</td>
      </tr>
      <tr>
          <td>中台</td>
          <td>即時在線</td>
          <td>session.active.count</td>
          <td>Collector 計算</td>
          <td>上線後</td>
          <td>即時大屏</td>
          <td>小時聚合 90d</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>四類事件的基礎定義 → <a href="/blog/monitoring/01-mental-model/four-event-types/" data-link-title="四類事件的完整定義" data-link-desc="Event / Error / Metric / Lifecycle 四類事件各自的語意、觸發時機和典型用途 — 分類是監控體系的統一語言">四類事件的完整定義</a></li>
<li>事件枚舉的方法論 → <a href="/blog/monitoring/01-mental-model/event-enumeration-method/" data-link-title="事件枚舉與補齊檢查" data-link-desc="從操作盤點系統性地推導出完整的事件清單 — 四類補齊檢查確保沒有遺漏、粒度判準確保每個事件只記一個事實">事件枚舉與補齊檢查</a></li>
<li>前端感測器的具體設計 → <a href="/blog/monitoring/03-sdk-design/frontend-sensor-design/" data-link-title="前端感測器設計" data-link-desc="什麼行為值得埋感測器、每類感測器的實作方式、取樣策略和效能影響 — 和 auto-intercept 的被動攔截互補">前端感測器設計</a></li>
<li>感測器的生命週期控制 → <a href="/blog/monitoring/03-sdk-design/sensor-lifecycle-management/" data-link-title="感測器生命週期管理" data-link-desc="產品生命週期的五個階段各啟用什麼感測器 — feature flag 整合、取樣率動態調整、感測器開關的可觀察性">感測器生命週期管理</a></li>
<li>查詢消費模式的完整展開 → <a href="/blog/monitoring/04-collector/query-consumption-patterns/" data-link-title="查詢消費模式" data-link-desc="Debug / Alerting / 產品決策 / 安全審計 / 效能監控 — 五種查詢場景各需要什麼事件、什麼欄位、什麼查詢模式">查詢消費模式</a></li>
</ul>
]]></content:encoded></item><item><title>推薦系統概論</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/recommendation-overview/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/recommendation-overview/</guid><description>&lt;p>推薦系統從使用者的歷史行為或物品的內容特徵推斷使用者可能感興趣的物品。三種基本方法各自依賴不同的資料：collaborative filtering 依賴使用者行為矩陣，content-based 依賴物品特徵，混合方法結合兩者。&lt;/p>
&lt;h2 id="collaborative-filtering">Collaborative Filtering&lt;/h2>
&lt;p>Collaborative filtering 的核心假設是「和你行為相似的人喜歡的東西，你也可能喜歡」。它不分析物品的內容，只看使用者的行為模式。&lt;/p>
&lt;h3 id="user-based">User-based&lt;/h3>
&lt;p>找到和目標使用者行為最相似的一群人（neighbors），把 neighbors 互動過但目標使用者沒互動過的物品推薦給目標使用者。&lt;/p>
&lt;p>資料需求：使用者-物品互動矩陣（user × item matrix），每格是評分、點擊、購買等互動訊號。&lt;/p>
&lt;p>挑戰：使用者數量增加時，計算使用者相似度的成本呈平方增長。冷啟動問題 — 新使用者沒有足夠的互動歷史來找到 neighbors。&lt;/p>
&lt;h3 id="item-based">Item-based&lt;/h3>
&lt;p>計算物品之間的相似度（根據哪些使用者同時互動過這兩個物品），推薦和使用者已互動物品相似的物品。&lt;/p>
&lt;p>資料需求：同上，但相似度計算的維度是物品而非使用者。&lt;/p>
&lt;p>優勢：物品的相似度矩陣比使用者相似度穩定（物品不會突然改變行為，使用者會），可以離線計算和快取。Amazon 的「購買此商品的人也買了」就是 item-based collaborative filtering。&lt;/p>
&lt;h2 id="content-based-filtering">Content-based Filtering&lt;/h2>
&lt;p>Content-based filtering 分析物品的內容特徵，推薦和使用者過去喜歡的物品內容相似的物品。&lt;/p>
&lt;p>資料需求：每個物品的特徵向量（genre、author、price range、keywords）和使用者的偏好 profile（從歷史互動推斷）。&lt;/p>
&lt;p>優勢：不依賴其他使用者的行為 — 單一使用者就能產生推薦。新物品只要有特徵描述就能被推薦（解決 collaborative filtering 的新物品冷啟動）。&lt;/p>
&lt;p>挑戰：推薦結果傾向和使用者歷史行為相似，缺乏意外發現（serendipity）。特徵工程的品質直接影響推薦品質 — 物品的特徵描述不完整或不準確，推薦就不準確。&lt;/p>
&lt;h2 id="混合方法">混合方法&lt;/h2>
&lt;p>結合 collaborative filtering 和 content-based 的優勢，減少各自的弱點。&lt;/p>
&lt;h3 id="加權混合">加權混合&lt;/h3>
&lt;p>兩種方法各自產生推薦清單，用加權分數合併。權重可以固定，也可以根據情境動態調整（新使用者偏重 content-based，老使用者偏重 collaborative filtering）。&lt;/p>
&lt;h3 id="特徵增強">特徵增強&lt;/h3>
&lt;p>用 content-based 的特徵增強 collaborative filtering 的矩陣。使用者-物品互動矩陣加上物品的內容特徵，讓相似度計算同時考慮行為和內容。&lt;/p>
&lt;h3 id="級聯">級聯&lt;/h3>
&lt;p>先用一種方法粗篩，再用另一種方法排序。Collaborative filtering 產生候選清單，content-based 根據使用者的內容偏好排序。&lt;/p>
&lt;h2 id="行為事件在推薦系統的角色">行為事件在推薦系統的角色&lt;/h2>
&lt;p>推薦系統的輸入是使用者的互動行為 — 瀏覽、點擊、加入購物車、購買、評分。這些互動行為就是行為事件（&lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/" data-link-title="模組一：監控心智模型" data-link-desc="四類事件（event / error / metric / lifecycle）的分類與收集策略">模組一 心智模型&lt;/a>）的 event 類型。&lt;/p>
&lt;p>行為事件的設計直接影響推薦系統的資料品質。事件的粒度決定了推薦的精細度 — 只記錄「頁面瀏覽」比記錄「頁面瀏覽 + 停留時間 + 滾動深度」的推薦信號弱。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>使用者分群的工程實作 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群&lt;/a>&lt;/li>
&lt;li>行為事件設計 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計&lt;/a>&lt;/li>
&lt;li>自架方案的分析能力邊界 → &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>推薦系統從使用者的歷史行為或物品的內容特徵推斷使用者可能感興趣的物品。三種基本方法各自依賴不同的資料：collaborative filtering 依賴使用者行為矩陣，content-based 依賴物品特徵，混合方法結合兩者。</p>
<h2 id="collaborative-filtering">Collaborative Filtering</h2>
<p>Collaborative filtering 的核心假設是「和你行為相似的人喜歡的東西，你也可能喜歡」。它不分析物品的內容，只看使用者的行為模式。</p>
<h3 id="user-based">User-based</h3>
<p>找到和目標使用者行為最相似的一群人（neighbors），把 neighbors 互動過但目標使用者沒互動過的物品推薦給目標使用者。</p>
<p>資料需求：使用者-物品互動矩陣（user × item matrix），每格是評分、點擊、購買等互動訊號。</p>
<p>挑戰：使用者數量增加時，計算使用者相似度的成本呈平方增長。冷啟動問題 — 新使用者沒有足夠的互動歷史來找到 neighbors。</p>
<h3 id="item-based">Item-based</h3>
<p>計算物品之間的相似度（根據哪些使用者同時互動過這兩個物品），推薦和使用者已互動物品相似的物品。</p>
<p>資料需求：同上，但相似度計算的維度是物品而非使用者。</p>
<p>優勢：物品的相似度矩陣比使用者相似度穩定（物品不會突然改變行為，使用者會），可以離線計算和快取。Amazon 的「購買此商品的人也買了」就是 item-based collaborative filtering。</p>
<h2 id="content-based-filtering">Content-based Filtering</h2>
<p>Content-based filtering 分析物品的內容特徵，推薦和使用者過去喜歡的物品內容相似的物品。</p>
<p>資料需求：每個物品的特徵向量（genre、author、price range、keywords）和使用者的偏好 profile（從歷史互動推斷）。</p>
<p>優勢：不依賴其他使用者的行為 — 單一使用者就能產生推薦。新物品只要有特徵描述就能被推薦（解決 collaborative filtering 的新物品冷啟動）。</p>
<p>挑戰：推薦結果傾向和使用者歷史行為相似，缺乏意外發現（serendipity）。特徵工程的品質直接影響推薦品質 — 物品的特徵描述不完整或不準確，推薦就不準確。</p>
<h2 id="混合方法">混合方法</h2>
<p>結合 collaborative filtering 和 content-based 的優勢，減少各自的弱點。</p>
<h3 id="加權混合">加權混合</h3>
<p>兩種方法各自產生推薦清單，用加權分數合併。權重可以固定，也可以根據情境動態調整（新使用者偏重 content-based，老使用者偏重 collaborative filtering）。</p>
<h3 id="特徵增強">特徵增強</h3>
<p>用 content-based 的特徵增強 collaborative filtering 的矩陣。使用者-物品互動矩陣加上物品的內容特徵，讓相似度計算同時考慮行為和內容。</p>
<h3 id="級聯">級聯</h3>
<p>先用一種方法粗篩，再用另一種方法排序。Collaborative filtering 產生候選清單，content-based 根據使用者的內容偏好排序。</p>
<h2 id="行為事件在推薦系統的角色">行為事件在推薦系統的角色</h2>
<p>推薦系統的輸入是使用者的互動行為 — 瀏覽、點擊、加入購物車、購買、評分。這些互動行為就是行為事件（<a href="/blog/monitoring/01-mental-model/" data-link-title="模組一：監控心智模型" data-link-desc="四類事件（event / error / metric / lifecycle）的分類與收集策略">模組一 心智模型</a>）的 event 類型。</p>
<p>行為事件的設計直接影響推薦系統的資料品質。事件的粒度決定了推薦的精細度 — 只記錄「頁面瀏覽」比記錄「頁面瀏覽 + 停留時間 + 滾動深度」的推薦信號弱。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>使用者分群的工程實作 → <a href="/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群</a></li>
<li>行為事件設計 → <a href="/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計</a></li>
<li>自架方案的分析能力邊界 → <a href="/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析</a></li>
</ul>
]]></content:encoded></item><item><title>RFM 分群</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/rfm-segmentation/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/rfm-segmentation/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/rfm/" data-link-title="RFM" data-link-desc="說明用 Recency / Frequency / Monetary 三個維度把使用者分成可操作群組的分群方法">RFM&lt;/a> 分群用三個維度衡量使用者的價值：Recency（最近一次互動是多久前）、Frequency（互動的頻率）、Monetary（互動的金額或價值）。三個維度各自獨立評分，組合成使用者的 RFM profile，驅動差異化的營運策略。&lt;/p>
&lt;h2 id="三個維度">三個維度&lt;/h2>
&lt;h3 id="recency最近一次互動的時間距離">Recency：最近一次互動的時間距離&lt;/h3>
&lt;p>計算使用者最後一次有意義的互動到現在的天數。「有意義的互動」取決於業務定義 — 電商是最後一次購買，SaaS 是最後一次登入，媒體是最後一次內容消費。&lt;/p>
&lt;p>Recency 的價值在於「最近互動的使用者比很久沒來的使用者更可能再次互動」。Recency 高（最近才來）的使用者是活躍群體，Recency 低（很久沒來）的使用者是流失風險群體。&lt;/p>
&lt;h3 id="frequency互動的頻率">Frequency：互動的頻率&lt;/h3>
&lt;p>計算使用者在特定時間窗口內的互動次數。時間窗口取決於業務節奏 — 日用品電商看近 90 天的購買次數，SaaS 看近 30 天的登入次數。&lt;/p>
&lt;p>Frequency 區分「偶爾來的使用者」和「常客」。高頻使用者是產品的核心用戶群，他們的行為和需求代表產品的核心價值。&lt;/p>
&lt;h3 id="monetary互動的價值">Monetary：互動的價值&lt;/h3>
&lt;p>計算使用者在特定時間窗口內貢獻的總金額。適用於有直接收入的業務（電商、訂閱服務）。&lt;/p>
&lt;p>沒有直接收入的產品可以用替代指標：內容平台用消費的內容數量，社群平台用產生的內容數量，工具類產品用使用的功能數量。替代指標的選擇依據是「哪個行為最能代表使用者的投入程度」。&lt;/p>
&lt;h2 id="rfm-分數計算">RFM 分數計算&lt;/h2>
&lt;p>每個維度獨立評分，通常用 1-5 分。評分方式有兩種：&lt;/p>
&lt;h3 id="等距分割">等距分割&lt;/h3>
&lt;p>把每個維度的值域等分成 5 段。Recency 0-6 天 = 5 分、7-13 天 = 4 分、依此類推。&lt;/p>
&lt;p>優點是簡單直覺；缺點是不考慮使用者分佈 — 如果大部分使用者的 Recency 在 0-6 天，5 分的群體佔大多數，分群的鑑別度低。&lt;/p>
&lt;h3 id="等量分割分位數">等量分割（分位數）&lt;/h3>
&lt;p>用分位數確保每個分數段的使用者數量大致相等。前 20% 的 Recency = 5 分、次 20% = 4 分。&lt;/p>
&lt;p>優點是每個分數段有足夠的使用者數量做分析；缺點是分數的業務意義不固定 — 5 分代表的天數取決於使用者分佈，不是固定的閾值。&lt;/p>
&lt;h2 id="rfm-群體定義">RFM 群體定義&lt;/h2>
&lt;p>三個維度各 5 分，組合出 125 種 RFM profile（5 × 5 × 5）。實務上不需要 125 種策略，通常歸納成 5-8 個有業務意義的群體：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>群體&lt;/th>
 &lt;th>RFM 特徵&lt;/th>
 &lt;th>描述&lt;/th>
 &lt;th>策略方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>冠軍客戶&lt;/td>
 &lt;td>R5 F5 M5&lt;/td>
 &lt;td>最近才來、經常來、消費高&lt;/td>
 &lt;td>維持關係、VIP 待遇&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>忠實客戶&lt;/td>
 &lt;td>R4-5 F4-5 M3-5&lt;/td>
 &lt;td>經常來、消費中到高&lt;/td>
 &lt;td>交叉銷售、推薦&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>潛力客戶&lt;/td>
 &lt;td>R4-5 F1-2 M1-2&lt;/td>
 &lt;td>最近才來、但頻率和消費低&lt;/td>
 &lt;td>引導更多互動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>沉睡客戶&lt;/td>
 &lt;td>R1-2 F3-5 M3-5&lt;/td>
 &lt;td>曾經活躍但很久沒來&lt;/td>
 &lt;td>挽回活動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流失客戶&lt;/td>
 &lt;td>R1 F1 M1&lt;/td>
 &lt;td>很久沒來、頻率低、消費低&lt;/td>
 &lt;td>評估挽回成本效益&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="工程實作">工程實作&lt;/h2>
&lt;p>RFM 計算的輸入是使用者的行為事件。從 collector 的 JSONL 資料計算 RFM：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>擷取&lt;/strong>：篩選目標事件（購買、登入、使用功能），按 user_id 分群&lt;/li>
&lt;li>&lt;strong>計算 R&lt;/strong>：每個 user_id 的最新事件時間到現在的天數&lt;/li>
&lt;li>&lt;strong>計算 F&lt;/strong>：每個 user_id 在時間窗口內的事件數量&lt;/li>
&lt;li>&lt;strong>計算 M&lt;/strong>：每個 user_id 在時間窗口內的 monetary 屬性加總&lt;/li>
&lt;li>&lt;strong>評分&lt;/strong>：對 R/F/M 各自用分位數或等距分割評分&lt;/li>
&lt;li>&lt;strong>分群&lt;/strong>：根據 RFM 分數組合定義群體&lt;/li>
&lt;/ol>
&lt;p>這個計算可以用 SQL（如果資料在資料庫）或 Python pandas（如果資料在 JSONL 檔案）完成。定期重算（每天或每週），產出使用者群體標籤。&lt;/p>
&lt;p>RFM 分群需要的資料可以從自架 collector 提取 — &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析&lt;/a>展示了 grep + jq 在自架環境中的分析能力和邊界。RFM 分出的群體還可以用 &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="按共同特徵分群、比較不同群體的留存率和行為差異 — 從「平均值」到「誰在用、誰離開了」">Cohort analysis&lt;/a> 追蹤留存趨勢，兩種分析互補。分群和分析的前提是正確的&lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計&lt;/a> — 事件的屬性決定了 R/F/M 能否被計算。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/monitoring/knowledge-cards/rfm/" data-link-title="RFM" data-link-desc="說明用 Recency / Frequency / Monetary 三個維度把使用者分成可操作群組的分群方法">RFM</a> 分群用三個維度衡量使用者的價值：Recency（最近一次互動是多久前）、Frequency（互動的頻率）、Monetary（互動的金額或價值）。三個維度各自獨立評分，組合成使用者的 RFM profile，驅動差異化的營運策略。</p>
<h2 id="三個維度">三個維度</h2>
<h3 id="recency最近一次互動的時間距離">Recency：最近一次互動的時間距離</h3>
<p>計算使用者最後一次有意義的互動到現在的天數。「有意義的互動」取決於業務定義 — 電商是最後一次購買，SaaS 是最後一次登入，媒體是最後一次內容消費。</p>
<p>Recency 的價值在於「最近互動的使用者比很久沒來的使用者更可能再次互動」。Recency 高（最近才來）的使用者是活躍群體，Recency 低（很久沒來）的使用者是流失風險群體。</p>
<h3 id="frequency互動的頻率">Frequency：互動的頻率</h3>
<p>計算使用者在特定時間窗口內的互動次數。時間窗口取決於業務節奏 — 日用品電商看近 90 天的購買次數，SaaS 看近 30 天的登入次數。</p>
<p>Frequency 區分「偶爾來的使用者」和「常客」。高頻使用者是產品的核心用戶群，他們的行為和需求代表產品的核心價值。</p>
<h3 id="monetary互動的價值">Monetary：互動的價值</h3>
<p>計算使用者在特定時間窗口內貢獻的總金額。適用於有直接收入的業務（電商、訂閱服務）。</p>
<p>沒有直接收入的產品可以用替代指標：內容平台用消費的內容數量，社群平台用產生的內容數量，工具類產品用使用的功能數量。替代指標的選擇依據是「哪個行為最能代表使用者的投入程度」。</p>
<h2 id="rfm-分數計算">RFM 分數計算</h2>
<p>每個維度獨立評分，通常用 1-5 分。評分方式有兩種：</p>
<h3 id="等距分割">等距分割</h3>
<p>把每個維度的值域等分成 5 段。Recency 0-6 天 = 5 分、7-13 天 = 4 分、依此類推。</p>
<p>優點是簡單直覺；缺點是不考慮使用者分佈 — 如果大部分使用者的 Recency 在 0-6 天，5 分的群體佔大多數，分群的鑑別度低。</p>
<h3 id="等量分割分位數">等量分割（分位數）</h3>
<p>用分位數確保每個分數段的使用者數量大致相等。前 20% 的 Recency = 5 分、次 20% = 4 分。</p>
<p>優點是每個分數段有足夠的使用者數量做分析；缺點是分數的業務意義不固定 — 5 分代表的天數取決於使用者分佈，不是固定的閾值。</p>
<h2 id="rfm-群體定義">RFM 群體定義</h2>
<p>三個維度各 5 分，組合出 125 種 RFM profile（5 × 5 × 5）。實務上不需要 125 種策略，通常歸納成 5-8 個有業務意義的群體：</p>
<table>
  <thead>
      <tr>
          <th>群體</th>
          <th>RFM 特徵</th>
          <th>描述</th>
          <th>策略方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>冠軍客戶</td>
          <td>R5 F5 M5</td>
          <td>最近才來、經常來、消費高</td>
          <td>維持關係、VIP 待遇</td>
      </tr>
      <tr>
          <td>忠實客戶</td>
          <td>R4-5 F4-5 M3-5</td>
          <td>經常來、消費中到高</td>
          <td>交叉銷售、推薦</td>
      </tr>
      <tr>
          <td>潛力客戶</td>
          <td>R4-5 F1-2 M1-2</td>
          <td>最近才來、但頻率和消費低</td>
          <td>引導更多互動</td>
      </tr>
      <tr>
          <td>沉睡客戶</td>
          <td>R1-2 F3-5 M3-5</td>
          <td>曾經活躍但很久沒來</td>
          <td>挽回活動</td>
      </tr>
      <tr>
          <td>流失客戶</td>
          <td>R1 F1 M1</td>
          <td>很久沒來、頻率低、消費低</td>
          <td>評估挽回成本效益</td>
      </tr>
  </tbody>
</table>
<h2 id="工程實作">工程實作</h2>
<p>RFM 計算的輸入是使用者的行為事件。從 collector 的 JSONL 資料計算 RFM：</p>
<ol>
<li><strong>擷取</strong>：篩選目標事件（購買、登入、使用功能），按 user_id 分群</li>
<li><strong>計算 R</strong>：每個 user_id 的最新事件時間到現在的天數</li>
<li><strong>計算 F</strong>：每個 user_id 在時間窗口內的事件數量</li>
<li><strong>計算 M</strong>：每個 user_id 在時間窗口內的 monetary 屬性加總</li>
<li><strong>評分</strong>：對 R/F/M 各自用分位數或等距分割評分</li>
<li><strong>分群</strong>：根據 RFM 分數組合定義群體</li>
</ol>
<p>這個計算可以用 SQL（如果資料在資料庫）或 Python pandas（如果資料在 JSONL 檔案）完成。定期重算（每天或每週），產出使用者群體標籤。</p>
<p>RFM 分群需要的資料可以從自架 collector 提取 — <a href="/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析</a>展示了 grep + jq 在自架環境中的分析能力和邊界。RFM 分出的群體還可以用 <a href="/blog/monitoring/08-business-analytics/cohort-analysis/" data-link-title="Cohort Analysis" data-link-desc="按共同特徵分群、比較不同群體的留存率和行為差異 — 從「平均值」到「誰在用、誰離開了」">Cohort analysis</a> 追蹤留存趨勢，兩種分析互補。分群和分析的前提是正確的<a href="/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計</a> — 事件的屬性決定了 R/F/M 能否被計算。</p>
]]></content:encoded></item><item><title>從 collector 資料做基礎 funnel 分析</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/self-hosted-funnel/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/self-hosted-funnel/</guid><description>&lt;p>自架 collector 收集的事件資料可以做基礎的 funnel 分析，不需要商業方案。分析的深度取決於 storage backend 的查詢能力 — SQLite 層能做每步事件計數，PostgreSQL 層能做 session 級轉換率分析。功能分層的完整定義見 &lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇&lt;/a>。&lt;/p>
&lt;h2 id="定義-funnel-步驟">定義 funnel 步驟&lt;/h2>
&lt;p>Funnel 分析的第一步是列出每一步和對應的事件名稱。以一個透過 WebSocket 連接遠端終端機的 app 連線流程為例：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>步驟&lt;/th>
 &lt;th>事件名稱&lt;/th>
 &lt;th>意義&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1&lt;/td>
 &lt;td>terminal.connect.start&lt;/td>
 &lt;td>使用者點擊連線&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2&lt;/td>
 &lt;td>auth.biometric.success&lt;/td>
 &lt;td>生物辨識通過&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3&lt;/td>
 &lt;td>terminal.connect.done&lt;/td>
 &lt;td>WebSocket 連線成功&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>4&lt;/td>
 &lt;td>terminal.input.submit&lt;/td>
 &lt;td>使用者開始打字&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="sqlite-層每步事件計數">SQLite 層：每步事件計數&lt;/h2>
&lt;p>SQLite backend 能做的 funnel 是「每步有多少事件觸發」— 單表 GROUP BY，不需要跨事件 JOIN。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">count&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">IN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;terminal.connect.start&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;auth.biometric.success&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;terminal.connect.done&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;terminal.input.submit&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ts&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;now&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;-7 days&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>步驟 N 的轉換率 = 步驟 N 的事件數 / 步驟 N-1 的事件數。流失率 = 1 - 轉換率。&lt;/p>
&lt;h3 id="能做的">能做的&lt;/h3>
&lt;ul>
&lt;li>每步事件計數（單表 GROUP BY）&lt;/li>
&lt;li>按 source.version 或 source.platform 分群（加 WHERE 條件）&lt;/li>
&lt;li>按天/按週看趨勢（strftime 分桶 + GROUP BY）&lt;/li>
&lt;/ul>
&lt;h3 id="做不到的">做不到的&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Session 級轉換率&lt;/strong>：「同一個 session 完成步驟 1 到步驟 4 的比例」需要 JOIN 同 session 的多個事件、跨所有 session 聚合。SQLite 能做這個 JOIN，但在大量 session 時效能不足。&lt;/li>
&lt;li>&lt;strong>步驟間耗時&lt;/strong>：「使用者在步驟 1 和步驟 2 之間等了多久」需要 self-join on session_id + timestamp 差值計算。&lt;/li>
&lt;li>&lt;strong>漏斗順序驗證&lt;/strong>：確認使用者是按 1→2→3→4 順序完成、不是跳步。&lt;/li>
&lt;/ul>
&lt;h2 id="postgresql-層session-級-funnel">PostgreSQL 層：Session 級 funnel&lt;/h2>
&lt;p>PostgreSQL backend 提供 window function 和高效 JOIN，能做完整的 session 級 funnel 分析。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="k">WITH&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_steps&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">ROW_NUMBER&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">OVER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PARTITION&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">ORDER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ts&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">step_order&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">IN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;terminal.connect.start&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;auth.biometric.success&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;terminal.connect.done&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;terminal.input.submit&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ts&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">NOW&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">INTERVAL&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;7 days&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">session_max_step&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">MAX&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">step_order&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">reached&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_steps&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">reached&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">sessions&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_max_step&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">reached&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">ORDER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">reached&lt;/span>&lt;span class="p">;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="新增能力">新增能力&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Session 級轉換率&lt;/strong>：每個 session 到達了哪一步、在哪一步流失&lt;/li>
&lt;li>&lt;strong>步驟間耗時&lt;/strong>：LAG window function 計算相鄰步驟的 timestamp 差值&lt;/li>
&lt;li>&lt;strong>漏斗順序驗證&lt;/strong>：用 ROW_NUMBER + CASE 確認步驟順序&lt;/li>
&lt;li>&lt;strong>Cohort 分群的 funnel&lt;/strong>：按使用者註冊日期 / 版本 / 平台分群看不同 cohort 的 funnel 差異&lt;/li>
&lt;/ul>
&lt;h2 id="jsonl-匯出後的臨時分析">JSONL 匯出後的臨時分析&lt;/h2>
&lt;p>Collector 的 &lt;code>monitor export --format=jsonl&lt;/code> 可以匯出事件為 JSONL 格式。匯出後用 grep + jq 做一次性的臨時分析：&lt;/p></description><content:encoded><![CDATA[<p>自架 collector 收集的事件資料可以做基礎的 funnel 分析，不需要商業方案。分析的深度取決於 storage backend 的查詢能力 — SQLite 層能做每步事件計數，PostgreSQL 層能做 session 級轉換率分析。功能分層的完整定義見 <a href="/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇</a>。</p>
<h2 id="定義-funnel-步驟">定義 funnel 步驟</h2>
<p>Funnel 分析的第一步是列出每一步和對應的事件名稱。以一個透過 WebSocket 連接遠端終端機的 app 連線流程為例：</p>
<table>
  <thead>
      <tr>
          <th>步驟</th>
          <th>事件名稱</th>
          <th>意義</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>terminal.connect.start</td>
          <td>使用者點擊連線</td>
      </tr>
      <tr>
          <td>2</td>
          <td>auth.biometric.success</td>
          <td>生物辨識通過</td>
      </tr>
      <tr>
          <td>3</td>
          <td>terminal.connect.done</td>
          <td>WebSocket 連線成功</td>
      </tr>
      <tr>
          <td>4</td>
          <td>terminal.input.submit</td>
          <td>使用者開始打字</td>
      </tr>
  </tbody>
</table>
<h2 id="sqlite-層每步事件計數">SQLite 層：每步事件計數</h2>
<p>SQLite backend 能做的 funnel 是「每步有多少事件觸發」— 單表 GROUP BY，不需要跨事件 JOIN。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="k">count</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w"></span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w"></span><span class="k">WHERE</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="k">IN</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;terminal.connect.start&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;auth.biometric.success&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">               </span><span class="s1">&#39;terminal.connect.done&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;terminal.input.submit&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">  </span><span class="k">AND</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">datetime</span><span class="p">(</span><span class="s1">&#39;now&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;-7 days&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w"></span><span class="k">GROUP</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">name</span><span class="p">;</span></span></span></code></pre></div><p>步驟 N 的轉換率 = 步驟 N 的事件數 / 步驟 N-1 的事件數。流失率 = 1 - 轉換率。</p>
<h3 id="能做的">能做的</h3>
<ul>
<li>每步事件計數（單表 GROUP BY）</li>
<li>按 source.version 或 source.platform 分群（加 WHERE 條件）</li>
<li>按天/按週看趨勢（strftime 分桶 + GROUP BY）</li>
</ul>
<h3 id="做不到的">做不到的</h3>
<ul>
<li><strong>Session 級轉換率</strong>：「同一個 session 完成步驟 1 到步驟 4 的比例」需要 JOIN 同 session 的多個事件、跨所有 session 聚合。SQLite 能做這個 JOIN，但在大量 session 時效能不足。</li>
<li><strong>步驟間耗時</strong>：「使用者在步驟 1 和步驟 2 之間等了多久」需要 self-join on session_id + timestamp 差值計算。</li>
<li><strong>漏斗順序驗證</strong>：確認使用者是按 1→2→3→4 順序完成、不是跳步。</li>
</ul>
<h2 id="postgresql-層session-級-funnel">PostgreSQL 層：Session 級 funnel</h2>
<p>PostgreSQL backend 提供 window function 和高效 JOIN，能做完整的 session 級 funnel 分析。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">WITH</span><span class="w"> </span><span class="n">session_steps</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">  </span><span class="k">SELECT</span><span class="w"> </span><span class="n">session_id</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">         </span><span class="n">ROW_NUMBER</span><span class="p">()</span><span class="w"> </span><span class="n">OVER</span><span class="w"> </span><span class="p">(</span><span class="n">PARTITION</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">session_id</span><span class="w"> </span><span class="k">ORDER</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">ts</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">step_order</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">  </span><span class="k">WHERE</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="k">IN</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;terminal.connect.start&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;auth.biometric.success&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">                 </span><span class="s1">&#39;terminal.connect.done&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;terminal.input.submit&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">    </span><span class="k">AND</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">NOW</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nb">INTERVAL</span><span class="w"> </span><span class="s1">&#39;7 days&#39;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w"></span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w"></span><span class="n">session_max_step</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">  </span><span class="k">SELECT</span><span class="w"> </span><span class="n">session_id</span><span class="p">,</span><span class="w"> </span><span class="k">MAX</span><span class="p">(</span><span class="n">step_order</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">reached</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">  </span><span class="k">FROM</span><span class="w"> </span><span class="n">session_steps</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">  </span><span class="k">GROUP</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">session_id</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w"></span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w"></span><span class="k">SELECT</span><span class="w"> </span><span class="n">reached</span><span class="p">,</span><span class="w"> </span><span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">sessions</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w"></span><span class="k">FROM</span><span class="w"> </span><span class="n">session_max_step</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w"></span><span class="k">GROUP</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">reached</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w"></span><span class="k">ORDER</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">reached</span><span class="p">;</span></span></span></code></pre></div><h3 id="新增能力">新增能力</h3>
<ul>
<li><strong>Session 級轉換率</strong>：每個 session 到達了哪一步、在哪一步流失</li>
<li><strong>步驟間耗時</strong>：LAG window function 計算相鄰步驟的 timestamp 差值</li>
<li><strong>漏斗順序驗證</strong>：用 ROW_NUMBER + CASE 確認步驟順序</li>
<li><strong>Cohort 分群的 funnel</strong>：按使用者註冊日期 / 版本 / 平台分群看不同 cohort 的 funnel 差異</li>
</ul>
<h2 id="jsonl-匯出後的臨時分析">JSONL 匯出後的臨時分析</h2>
<p>Collector 的 <code>monitor export --format=jsonl</code> 可以匯出事件為 JSONL 格式。匯出後用 grep + jq 做一次性的臨時分析：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">for</span> step in terminal.connect.start auth.biometric.success terminal.connect.done terminal.input.submit<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="nv">count</span><span class="o">=</span><span class="k">$(</span>grep <span class="s2">&#34;\&#34;name\&#34;:\&#34;</span><span class="nv">$step</span><span class="s2">\&#34;&#34;</span> exported-events.jsonl <span class="p">|</span> wc -l<span class="k">)</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;</span><span class="nv">$step</span><span class="s2">: </span><span class="nv">$count</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="k">done</span></span></span></code></pre></div><p>JSONL 臨時分析適合「快速看一眼大概數字」的場景。持續性的 funnel 監控應該用 SQLite 或 PostgreSQL 的 SQL 查詢，結果穩定且可重現。</p>
<h2 id="自架-vs-商業方案">自架 vs 商業方案</h2>
<table>
  <thead>
      <tr>
          <th>需求</th>
          <th>自架能力</th>
          <th>商業方案</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>每步事件計數</td>
          <td>SQLite GROUP BY</td>
          <td>Mixpanel / Amplitude 內建</td>
      </tr>
      <tr>
          <td>Session 級轉換率</td>
          <td>PostgreSQL window function</td>
          <td>Mixpanel / Amplitude 內建</td>
      </tr>
      <tr>
          <td>視覺化 funnel 漏斗圖</td>
          <td>自建 dashboard</td>
          <td>商業方案內建、拖拉設定</td>
      </tr>
      <tr>
          <td>即時更新</td>
          <td>定期重算 + dashboard 刷新</td>
          <td>商業方案即時</td>
      </tr>
      <tr>
          <td>A/B test 分群 funnel</td>
          <td>PostgreSQL + feature flag</td>
          <td>Optimizely / LaunchDarkly 整合</td>
      </tr>
  </tbody>
</table>
<p>自用工具場景下，SQLite 層的每步事件計數通常足夠。商業產品需要 session 級分析時，PostgreSQL 層的 SQL 能力和商業方案的分析能力在功能上對等，差異在 UI 和設定便利性。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Funnel 分析的完整方法論 → <a href="/blog/monitoring/08-business-analytics/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="使用者在哪一步流失 — 從事件序列計算每步轉換率、找出流失最嚴重的步驟、區分設計問題和技術問題">Funnel analysis</a></li>
<li>事件設計如何影響分析品質 → <a href="/blog/monitoring/08-business-analytics/behavior-event-design/" data-link-title="行為事件設計" data-link-desc="事件命名規範、屬性設計、funnel 定義 — 行為分析的品質取決於事件設計的品質">行為事件設計</a></li>
<li>功能分層定義 → <a href="/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇</a></li>
<li>去識別化是分析的入場條件 → <a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七 資安與隱私</a></li>
</ul>
]]></content:encoded></item><item><title>模組八：行為資料的商業利用</title><link>https://tarrragon.github.io/blog/monitoring/08-business-analytics/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/08-business-analytics/</guid><description>&lt;p>回答「蒐集到的行為資料除了 debug，還能做什麼」。前提：&lt;a href="https://tarrragon.github.io/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七&lt;/a> 的去識別化是本模組的入場條件。&lt;/p>
&lt;h2 id="待寫章節">待寫章節&lt;/h2>
&lt;ul>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 行為事件設計（事件命名規範 / 屬性設計 / funnel 定義）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Funnel analysis（使用者在哪一步流失）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Cohort analysis（不同族群的留存率差異）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Attribution（使用者從哪來、哪個廣告帶來轉換）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> A/B test 的統計基礎（假設檢定 / 樣本量 / 多重比較）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 推薦系統概論（collaborative filtering / content-based / 混合）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> RFM 分群（Recency / Frequency / Monetary 的工程實作）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 從 collector 資料做基礎 funnel 分析（自架方案能做到哪裡）&lt;/li>
&lt;/ul>
&lt;h2 id="跨分類引用">跨分類引用&lt;/h2>
&lt;ul>
&lt;li>← &lt;a href="https://tarrragon.github.io/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">monitoring 模組七 資安&lt;/a>：去識別化是入場條件&lt;/li>
&lt;li>← &lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/" data-link-title="模組一：監控心智模型" data-link-desc="四類事件（event / error / metric / lifecycle）的分類與收集策略">monitoring 模組一 心智模型&lt;/a>：event 類事件是行為分析的原料&lt;/li>
&lt;li>← &lt;a href="https://tarrragon.github.io/blog/ux-design/01-screen-state-machine/" data-link-title="模組一：畫面狀態機設計" data-link-desc="畫面狀態矩陣（顯示 / 操作 / 進入 / 退出）— 退出路徑為空 = UX 死胡同">ux-design 模組一 畫面狀態機&lt;/a>：狀態轉換事件 → funnel 分析&lt;/li>
&lt;li>待建連結 → &lt;code>data-engineering/&lt;/code>（資料管線設計）&lt;/li>
&lt;li>待建連結 → &lt;code>statistics/&lt;/code>（A/B test 統計基礎）&lt;/li>
&lt;li>待建連結 → &lt;code>machine-learning/&lt;/code>（推薦系統架構）&lt;/li>
&lt;li>待建連結 → &lt;code>compliance/&lt;/code>（GDPR / CCPA / 個資法）&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>回答「蒐集到的行為資料除了 debug，還能做什麼」。前提：<a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七</a> 的去識別化是本模組的入場條件。</p>
<h2 id="待寫章節">待寫章節</h2>
<ul>
<li><input checked="" disabled="" type="checkbox"> 行為事件設計（事件命名規範 / 屬性設計 / funnel 定義）</li>
<li><input checked="" disabled="" type="checkbox"> Funnel analysis（使用者在哪一步流失）</li>
<li><input checked="" disabled="" type="checkbox"> Cohort analysis（不同族群的留存率差異）</li>
<li><input checked="" disabled="" type="checkbox"> Attribution（使用者從哪來、哪個廣告帶來轉換）</li>
<li><input checked="" disabled="" type="checkbox"> A/B test 的統計基礎（假設檢定 / 樣本量 / 多重比較）</li>
<li><input checked="" disabled="" type="checkbox"> 推薦系統概論（collaborative filtering / content-based / 混合）</li>
<li><input checked="" disabled="" type="checkbox"> RFM 分群（Recency / Frequency / Monetary 的工程實作）</li>
<li><input checked="" disabled="" type="checkbox"> 從 collector 資料做基礎 funnel 分析（自架方案能做到哪裡）</li>
</ul>
<h2 id="跨分類引用">跨分類引用</h2>
<ul>
<li>← <a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">monitoring 模組七 資安</a>：去識別化是入場條件</li>
<li>← <a href="/blog/monitoring/01-mental-model/" data-link-title="模組一：監控心智模型" data-link-desc="四類事件（event / error / metric / lifecycle）的分類與收集策略">monitoring 模組一 心智模型</a>：event 類事件是行為分析的原料</li>
<li>← <a href="/blog/ux-design/01-screen-state-machine/" data-link-title="模組一：畫面狀態機設計" data-link-desc="畫面狀態矩陣（顯示 / 操作 / 進入 / 退出）— 退出路徑為空 = UX 死胡同">ux-design 模組一 畫面狀態機</a>：狀態轉換事件 → funnel 分析</li>
<li>待建連結 → <code>data-engineering/</code>（資料管線設計）</li>
<li>待建連結 → <code>statistics/</code>（A/B test 統計基礎）</li>
<li>待建連結 → <code>machine-learning/</code>（推薦系統架構）</li>
<li>待建連結 → <code>compliance/</code>（GDPR / CCPA / 個資法）</li>
</ul>
]]></content:encoded></item><item><title>中台 Dashboard 設計</title><link>https://tarrragon.github.io/blog/monitoring/04-collector/dashboard-business/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/04-collector/dashboard-business/</guid><description>&lt;p>中台 dashboard 的消費者是營運單位和行銷單位，關心的是「使用者行為」和「商業指標」。這個 dashboard 和 &lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/dashboard-developer/" data-link-title="Developer Dashboard 設計" data-link-desc="Bug 在哪、多嚴重、怎麼重現 — Error 列表和趨勢的日常監控、Session 回放和 Stack trace 的深入 debug">Developer dashboard&lt;/a> 的消費對象不同 — 開發者看 stack trace 和 error 分佈，營運看漏斗轉換和留存率。&lt;/p>
&lt;p>中台 dashboard 的所有深入分析視圖都需要 PostgreSQL 層（&lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇&lt;/a>），因為它們依賴跨 session 的 JOIN 和大規模聚合查詢。SQLite 層只能提供基礎的事件計數。&lt;/p>
&lt;h2 id="日常監控視圖">日常監控視圖&lt;/h2>
&lt;h3 id="dau--mau">DAU / MAU&lt;/h3>
&lt;p>每日活躍使用者數（DAU）和每月活躍使用者數（MAU）的趨勢折線圖。活躍使用者的定義是「該時間段內至少有一筆 &lt;code>session.start&lt;/code> 事件的唯一 session」。&lt;/p>
&lt;p>DAU / MAU 比值（粘性指數）是產品健康的基本訊號 — 比值越高代表使用者回訪越頻繁。一般 SaaS 產品的 DAU/MAU 在 10-20% 為正常範圍，社交類產品期望 50% 以上。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- PostgreSQL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">date_trunc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ts&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">day&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">DISTINCT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dau&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">type&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;lifecycle&amp;#39;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;session.start&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ts&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">NOW&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">INTERVAL&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;30 days&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">day&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">ORDER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">day&lt;/span>&lt;span class="p">;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="核心漏斗">核心漏斗&lt;/h3>
&lt;p>主要業務流程的每步轉換率。漏斗的步驟從 &lt;a href="https://tarrragon.github.io/blog/monitoring/01-mental-model/motivation-to-event-mapping/" data-link-title="動機驅動的事件設計" data-link-desc="Debug / 商業 / 資安 / 效能四個動機各自需要什麼事件 — 從「為什麼收」反推「收什麼」和「什麼階段啟用」">動機驅動的事件設計&lt;/a> 的商業動機段定義。&lt;/p>
&lt;p>日常視圖顯示最近 7 天的整體轉換率 — 營運人員每天看「昨天的漏斗有沒有異常」。轉換率突然下降是產品問題的早期訊號（UI 改版影響操作流程、第三方服務異常阻擋流程）。&lt;/p>
&lt;h3 id="功能使用排行">功能使用排行&lt;/h3>
&lt;p>按 &lt;code>event.name&lt;/code> 計數的排行榜。營運用它判斷「哪些功能有人用、哪些沒人用」— 功能投資的 ROI 判斷依據。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- SQLite 層可用（基礎計數）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">usage_count&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">type&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;event&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ts&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;now&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;-7 days&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">ORDER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">usage_count&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DESC&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">LIMIT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">20&lt;/span>&lt;span class="p">;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>功能使用排行是 SQLite 層就能提供的視圖 — 單表 GROUP BY。&lt;/p>
&lt;h2 id="分析深入視圖">分析深入視圖&lt;/h2>
&lt;p>日常視圖發現異常後，營運人員進入分析視圖深入探究。所有分析視圖都需要 PostgreSQL 層。&lt;/p>
&lt;h3 id="funnel-漏斗圖">Funnel 漏斗圖&lt;/h3>
&lt;p>互動式漏斗圖：選擇步驟 → 看每步轉換率 → 點擊某步看流失使用者的行為。&lt;/p>
&lt;p>Funnel 需要 session 級 JOIN — 「同一個 session 完成了步驟 1 到步驟 N 中的哪些步驟」。完整的 SQL 查詢見 &lt;a href="https://tarrragon.github.io/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>中台 dashboard 的消費者是營運單位和行銷單位，關心的是「使用者行為」和「商業指標」。這個 dashboard 和 <a href="/blog/monitoring/04-collector/dashboard-developer/" data-link-title="Developer Dashboard 設計" data-link-desc="Bug 在哪、多嚴重、怎麼重現 — Error 列表和趨勢的日常監控、Session 回放和 Stack trace 的深入 debug">Developer dashboard</a> 的消費對象不同 — 開發者看 stack trace 和 error 分佈，營運看漏斗轉換和留存率。</p>
<p>中台 dashboard 的所有深入分析視圖都需要 PostgreSQL 層（<a href="/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇</a>），因為它們依賴跨 session 的 JOIN 和大規模聚合查詢。SQLite 層只能提供基礎的事件計數。</p>
<h2 id="日常監控視圖">日常監控視圖</h2>
<h3 id="dau--mau">DAU / MAU</h3>
<p>每日活躍使用者數（DAU）和每月活躍使用者數（MAU）的趨勢折線圖。活躍使用者的定義是「該時間段內至少有一筆 <code>session.start</code> 事件的唯一 session」。</p>
<p>DAU / MAU 比值（粘性指數）是產品健康的基本訊號 — 比值越高代表使用者回訪越頻繁。一般 SaaS 產品的 DAU/MAU 在 10-20% 為正常範圍，社交類產品期望 50% 以上。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- PostgreSQL
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="k">SELECT</span><span class="w"> </span><span class="n">date_trunc</span><span class="p">(</span><span class="s1">&#39;day&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">ts</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="k">day</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">       </span><span class="k">COUNT</span><span class="p">(</span><span class="k">DISTINCT</span><span class="w"> </span><span class="n">session_id</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">dau</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w"></span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w"></span><span class="k">WHERE</span><span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;lifecycle&#39;</span><span class="w"> </span><span class="k">AND</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;session.start&#39;</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">  </span><span class="k">AND</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">NOW</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nb">INTERVAL</span><span class="w"> </span><span class="s1">&#39;30 days&#39;</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w"></span><span class="k">GROUP</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="k">day</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w"></span><span class="k">ORDER</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="k">day</span><span class="p">;</span></span></span></code></pre></div><h3 id="核心漏斗">核心漏斗</h3>
<p>主要業務流程的每步轉換率。漏斗的步驟從 <a href="/blog/monitoring/01-mental-model/motivation-to-event-mapping/" data-link-title="動機驅動的事件設計" data-link-desc="Debug / 商業 / 資安 / 效能四個動機各自需要什麼事件 — 從「為什麼收」反推「收什麼」和「什麼階段啟用」">動機驅動的事件設計</a> 的商業動機段定義。</p>
<p>日常視圖顯示最近 7 天的整體轉換率 — 營運人員每天看「昨天的漏斗有沒有異常」。轉換率突然下降是產品問題的早期訊號（UI 改版影響操作流程、第三方服務異常阻擋流程）。</p>
<h3 id="功能使用排行">功能使用排行</h3>
<p>按 <code>event.name</code> 計數的排行榜。營運用它判斷「哪些功能有人用、哪些沒人用」— 功能投資的 ROI 判斷依據。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- SQLite 層可用（基礎計數）
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="k">SELECT</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">usage_count</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w"></span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w"></span><span class="k">WHERE</span><span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;event&#39;</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">  </span><span class="k">AND</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">datetime</span><span class="p">(</span><span class="s1">&#39;now&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;-7 days&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w"></span><span class="k">GROUP</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">name</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w"></span><span class="k">ORDER</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="n">usage_count</span><span class="w"> </span><span class="k">DESC</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w"></span><span class="k">LIMIT</span><span class="w"> </span><span class="mi">20</span><span class="p">;</span></span></span></code></pre></div><p>功能使用排行是 SQLite 層就能提供的視圖 — 單表 GROUP BY。</p>
<h2 id="分析深入視圖">分析深入視圖</h2>
<p>日常視圖發現異常後，營運人員進入分析視圖深入探究。所有分析視圖都需要 PostgreSQL 層。</p>
<h3 id="funnel-漏斗圖">Funnel 漏斗圖</h3>
<p>互動式漏斗圖：選擇步驟 → 看每步轉換率 → 點擊某步看流失使用者的行為。</p>
<p>Funnel 需要 session 級 JOIN — 「同一個 session 完成了步驟 1 到步驟 N 中的哪些步驟」。完整的 SQL 查詢見 <a href="/blog/monitoring/08-business-analytics/self-hosted-funnel/" data-link-title="從 collector 資料做基礎 funnel 分析" data-link-desc="SQLite 層能做什麼程度的 funnel、PostgreSQL 層提供什麼進階能力、JSONL 匯出後的臨時分析">從 collector 資料做基礎 funnel 分析</a>。</p>
<h3 id="cohort-留存表">Cohort 留存表</h3>
<p>按「使用者首次出現日期」分群的留存率矩陣。行是 cohort（第 N 週註冊的使用者），列是「第 1/2/3/…週的回訪率」。</p>
<p>需要的事件：<code>user.first_seen</code>（cohort 分群依據）+ <code>session.start</code>（回訪判定）。</p>
<p><code>user.first_seen</code> 是 collector 端計算的衍生事件 — 當某個 session_id 或 user identifier 在系統中第一次出現時記錄。和 SDK 端送來的原始事件不同，它的產生者是 collector 的計算邏輯。</p>
<h3 id="ab-測試結果">A/B 測試結果</h3>
<p>實驗的 variant 間轉換率比較 + 統計顯著性指標（p-value、信賴區間）。</p>
<p>需要的事件：<code>experiment.{name}.assigned</code>（分組）+ <code>experiment.{name}.converted</code>（轉換）。這些事件在 <a href="/blog/monitoring/01-mental-model/motivation-to-event-mapping/" data-link-title="動機驅動的事件設計" data-link-desc="Debug / 商業 / 資安 / 效能四個動機各自需要什麼事件 — 從「為什麼收」反推「收什麼」和「什麼階段啟用」">動機驅動的事件設計</a> 的 A/B 測試段定義。統計分析的方法見 <a href="/blog/monitoring/08-business-analytics/ab-test-statistics/" data-link-title="A/B Test 的統計基礎" data-link-desc="假設檢定、樣本量計算、多重比較校正 — A/B test 不只是「比較兩個數字」，統計方法決定結論是否可靠">A/B test 的統計基礎</a>。</p>
<h3 id="rfm-分群散佈圖">RFM 分群散佈圖</h3>
<p>三維度（Recency / Frequency / Monetary）的使用者分群。每個使用者計算 R/F/M 分數，按分數分群後在散佈圖上顯示。</p>
<p>需要的事件：event 類的購買/使用事件 + lifecycle 的 session 事件。計算方法見 <a href="/blog/monitoring/08-business-analytics/rfm-segmentation/" data-link-title="RFM 分群" data-link-desc="Recency / Frequency / Monetary 三維度的使用者分群 — 從行為事件計算 RFM 分數、定義使用者群體、驅動差異化策略">RFM 分群</a>。</p>
<h3 id="通路歸因">通路歸因</h3>
<p>使用者從哪裡來（哪個廣告、哪個推薦連結、自然流量），每個通路帶來多少轉換。</p>
<p>需要的事件：<code>attribution.install_source</code>（SDK 首次啟動時從 referrer / UTM 參數 / deep link 取得安裝來源）+ <code>conversion.{type}</code>（轉換事件）。</p>
<p><code>attribution.install_source</code> 只在 SDK 首次啟動時送一次。來源資訊的取得方式依平台不同 — Web 從 URL 的 UTM 參數取、mobile app 從 deferred deep link 或 install referrer API 取。</p>
<h2 id="需要的缺口事件">需要的缺口事件</h2>
<p>中台 dashboard 暴露了三個目前事件表未覆蓋的事件：</p>
<table>
  <thead>
      <tr>
          <th>事件名稱</th>
          <th>類型</th>
          <th>產生者</th>
          <th>用途</th>
          <th>為什麼缺</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>user.first_seen</td>
          <td>lifecycle</td>
          <td>Collector 計算</td>
          <td>Cohort 分群依據</td>
          <td>原始事件設計聚焦 SDK 端，衍生計算事件不在設計範圍</td>
      </tr>
      <tr>
          <td>attribution.install_source</td>
          <td>event</td>
          <td>SDK 首次啟動</td>
          <td>通路歸因</td>
          <td>只在首次啟動送一次的事件沒有被操作盤點覆蓋</td>
      </tr>
      <tr>
          <td>session.active.count</td>
          <td>metric</td>
          <td>Collector 計算</td>
          <td>即時在線大屏</td>
          <td>即時統計是 collector 端的衍生 metric</td>
      </tr>
  </tbody>
</table>
<p>這三個事件的共同特徵：前兩個是「只發生一次」的事件（首次出現、首次安裝），第三個是 collector 端的即時計算結果。操作盤點和四類補齊檢查聚焦在「反覆發生的使用者操作」，容易遺漏「只發生一次」的生命週期轉折點和 collector 端的衍生計算。</p>
<h2 id="中台的權限隔離">中台的權限隔離</h2>
<p>營運和行銷人員看行為資料，但不需要也不應該看到 stack trace、raw error message、session 級別的原始事件明細。權限隔離在 collector 的查詢 API 層實作 — 不同的 API scope 回傳不同粒度的資料。</p>
<table>
  <thead>
      <tr>
          <th>Scope</th>
          <th>可見</th>
          <th>不可見</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>devops</td>
          <td>collector 健康 metric、SDK 狀態</td>
          <td>業務事件明細</td>
      </tr>
      <tr>
          <td>developer</td>
          <td>全部事件、stack trace、session 回放</td>
          <td>無限制</td>
      </tr>
      <tr>
          <td>business</td>
          <td>聚合統計（funnel/cohort/count）、匿名行為</td>
          <td>stack trace、error raw data、session 原始事件</td>
      </tr>
  </tbody>
</table>
<p>Scope 的實作可以是 API key 分級（不同 key 有不同 scope）、或 HTTP header 帶 role。Day-one 可以跳過（自用場景只有 developer 一個角色），tripwire 是「第一個非開發者要看 dashboard 時加入 scope 機制」。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>DevOps dashboard 設計 → <a href="/blog/monitoring/04-collector/dashboard-devops/" data-link-title="DevOps Dashboard 設計" data-link-desc="Collector 和 SDK 是否健康 — 日常監控的服務狀態卡、吞吐量曲線、儲存用量，以及告警觸發後的排障視圖">DevOps Dashboard 設計</a></li>
<li>Developer dashboard 設計 → <a href="/blog/monitoring/04-collector/dashboard-developer/" data-link-title="Developer Dashboard 設計" data-link-desc="Bug 在哪、多嚴重、怎麼重現 — Error 列表和趨勢的日常監控、Session 回放和 Stack trace 的深入 debug">Developer Dashboard 設計</a></li>
<li>Funnel 分析的完整方法 → <a href="/blog/monitoring/08-business-analytics/funnel-analysis/" data-link-title="Funnel Analysis" data-link-desc="使用者在哪一步流失 — 從事件序列計算每步轉換率、找出流失最嚴重的步驟、區分設計問題和技術問題">Funnel analysis</a></li>
<li>功能分層與 Backend 選擇 → <a href="/blog/monitoring/04-collector/feature-tier-boundary/" data-link-title="功能分層與 Backend 選擇" data-link-desc="SQLite 層和 PostgreSQL 層各自承載哪些功能 — 分界線是查詢模式而非資料量、觸發升級的是功能需求而非規模成長">功能分層與 Backend 選擇</a></li>
<li>去識別化是中台 dashboard 的入場條件 → <a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">模組七 資安與隱私</a></li>
<li>畫面狀態矩陣定義了 funnel 步驟的操作來源 → <a href="/blog/ux-design/01-screen-state-machine/state-matrix-definition/" data-link-title="畫面狀態矩陣的定義與填寫方法" data-link-desc="四欄矩陣（顯示 / 可用操作 / 進入條件 / 退出路徑）的定義、填寫步驟和檢查規則 — 退出路徑為空 = UX 死胡同">畫面狀態矩陣</a></li>
</ul>
]]></content:encoded></item></channel></rss>