n8n Notion 自動化Notion 客戶資料同步n8n 訂單同步Notion 內容排程single source of truth

n8n + Notion 自動化實戰:把客戶、訂單、內容排程同步成單一真相來源

Notion 是好用的工作台但不是 CRM;用 n8n 把 Stripe 訂單、HubSpot 客戶、Postiz 內容排程同步進來,就變成中小企業的 single source of truth。本文用三條真實 pipeline 拆解 schema 設計、rate limit、雙向同步衝突解決,附 10 個 production blueprint。

N8NMarket 2026年5月16日 14 分鐘閱讀

中小企業最常見的悲劇:客戶資料在 HubSpot、訂單在 Stripe Dashboard、行銷內容在 Postiz、研究筆記在 Google Docs、合作會議記錄在 Slack。老闆問一句「上個月實際成交幾單,誰買的,哪些客戶 onboarding 卡住」,整個團隊翻五個工具拼三天,最後拿出來的數字還對不上。

這不是工具不夠多,是沒有 single source of truth。本文示範用 n8n 把三條主流資料管線都同步到 Notion,讓 Notion 變成「人看得懂、機器寫得進去、互相 linkable」的單一真相來源。三條 pipeline、10 個 blueprint、30 天落地節奏,全部照抄。

為什麼中小企業需要 single source of truth,而 Notion 為什麼適合(也適合不到哪裡)

先把問題講清楚:你需要的不是「另一個 CRM」,是「一個地方能看到所有客戶、訂單、內容的當前狀態」。

真實場景:5 個工具開的 5 個 truth

上個月幫一家 30 人規模的 SaaS 客戶做諮詢,他們的資料地圖是這樣:

  • HubSpot:客戶 contacts + deal pipeline,但沒接訂單
  • Stripe:訂單 + 訂閱狀態 + MRR,但沒寫客戶筆記
  • Notion:產品文件 + 客戶 onboarding checklist,但訂單狀態靠人工貼
  • Postiz:社群排程 + 文章發布,但效果數字回填靠人工
  • Slack:所有的「老闆問了沒人答」歷史紀錄

CSM 想知道「這個客戶有沒有續訂」要切到 Stripe,想知道「這個客戶 onboarding 卡哪」要切到 Notion,想知道「上次跟他通信什麼內容」要切到 Slack。每個動作切三個工具,30 個客戶就是 90 次切換,一天就是 4 小時純粹在找資料。

最後決議:所有「需要被人查的真相」全部同步進 Notion,原始系統照常運作,Notion 變成「總前台」。三個月後客戶查資料時間降了七成,老闆問月底 MRR 五秒就有答案。

Notion 適合做 SoT 的 3 個理由

第一,Notion 的 relation + rollup 已經夠像關聯式資料庫。一個 Customer page 透過 relation 連到多個 Order page,rollup 算出 LTV、最近訂購日、active subscription 數量,這套等同 SQL 的 LEFT JOIN + SUM,但完全不用寫 query。

第二,Notion 的權限模型適合中小企業。你可以把整個 Customer database 給銷售看,但 password / API key 那一欄只給工程師看;客戶要看自己的 onboarding 進度,給他單一 page 的 share link 就行。權限細到 property 等級,比大多數 SaaS 強。

第三,Notion 的人機介面友好。CRM 工具長得像 1998 年的 ERP 後台,新員工要學三天;Notion 像在用 Google Docs,新人 30 分鐘就上手。資料能被人看懂,才能被人用。

不適合的 2 個硬限制

第一,Notion API rate limit 是 3 requests/second/integration,遠低於正規後端。Stripe 大促一天 5000 筆訂單同步進來,沒做佇列就會撞限流,事件丟失。所以 Notion 不能做 transaction 系統,只能做 mirror。

第二,Notion 沒有真正的 unique constraint 與 foreign key。relation 是軟的(會接受空連結、會留 orphan 記錄)、property 沒有真正的 unique index、duplicate page 隨時可能被人手動建。production 同步必須在 n8n 那層做完整 idempotency 設計。

理解這兩個限制後,正確姿勢就清楚了:原始系統(HubSpot、Stripe、Postiz)是 SoT,Notion 是 SoT 的 human-readable mirror,n8n 是兩邊之間的 sync engine。

pipeline 1:客戶資料同步(HubSpot / Stripe Customer → Notion CRM database)

第一條 pipeline 永遠先做客戶同步。原因是訂單與內容都需要關聯到客戶,客戶沒進來其他都白做。

Notion CRM database schema 設計

開一個叫 Customers 的 Notion database,最小可用 schema 長這樣:

PropertyType來源備註
NameTitleHubSpot company name主要顯示
External IDRich TextHubSpot vid 或 Stripe customer id同步 idempotency 用,必填、必加 unique 標記
EmailEmailHubSpot給 CSM 直接 mailto
StageSelectHubSpot deal stage對應 sales pipeline
LTVNumberrollup from OrdersOrder relation 算出
Active SubscriptionNumberrollup from Orders同上
Last TouchDaten8n 每次 sync 時寫判斷哪些客戶超過 30 天沒互動
OwnerPerson手動Notion 內部分配
NotesPage Content手動CSM 寫客戶筆記
Source SystemSelectHubSpot / Stripe / Manual知道誰是真相

重點在 External ID 這一欄。Notion 沒有 unique constraint,所以同步邏輯不能寫成「找名字一樣的就 update」(會誤觸到同名客戶),必須是「先用 External ID 查 page,找到 → PATCH;找不到 → CREATE」。

關於要不要把 Stripe customer idHubSpot vid 分兩欄:建議合併成單一 External ID + 加 Source System,理由是後續 rollup / filter 邏輯會單純很多。如果客戶橫跨兩個系統(HubSpot 有 + Stripe 也有),建立兩筆 Customer page、用 relation 互指,比強迫合併乾淨。

n8n workflow 結構:Schedule Trigger + 雙向 upsert

工作流骨架:

Schedule Trigger (每 15 分鐘)

HubSpot:搜尋上次同步後 updatedAt > last_sync 的 contacts

SplitInBatches (batch size 10,因為 Notion 3 req/sec)

Function:把 HubSpot fields 映射成 Notion property payload

Notion:用 External ID 查找 page
  ├─ 找到 → PATCH (update properties)
  └─ 找不到 → POST (create page)

PostgreSQL:寫 sync log(external_id, action, timestamp, payload hash)

Wait 350ms(保留 buffer,避免併發跨 batch 撞限流)

迴圈下一個 batch

雙向同步要不要做?建議第一階段先做單向(HubSpot → Notion),等穩定 60 小時再加反向。反向的觸發點是「CSM 在 Notion 改 Owner / Stage」,用 Notion webhook(透過 Make 的中繼或 Notion automation)打回 n8n,再寫進 HubSpot。

Notion API rate limit 的批次與佇列策略

3 req/sec 不是嚴格節流,是「超過會回 429 + Retry-After header」。production 經驗:

  1. batch size 10:每 batch 跑完 wait 350ms,剛好踩在 ~2.8 req/sec 邊緣,留 buffer
  2. 每天初始全量 sync:開機後 5 分鐘內全量比對,補上昨晚漏的;之後每 15 分鐘 incremental
  3. 429 後 exponential backoff:第一次撞 1 秒、第二次 2 秒、第三次 4 秒,超過 8 秒直接寫 DLQ 表
  4. Notion integration 拆兩個:一個給寫入(這條 pipeline 用),一個給讀取(dashboard、查詢用),兩個 token rate limit 是分開計算的

連 retry 機制都還沒設計過?先把 n8n workflow 錯誤處理三層模式 那套接上來,再來談批次。

pipeline 2:訂單同步(Stripe webhook → Notion Order database)

訂單同步比客戶複雜,因為訂單會被退款、會被續訂、會被失敗,狀態流不是單向。

webhook → n8n → Notion 的 idempotency

Stripe webhook 一個事件 72 小時內最多重送 16 次,沒做去重等於同一筆訂單在 Notion 出現 16 條。前置處理跟 Stripe webhook 多步驟分支設計 一樣:簽章驗證 → event_id 去重 → 立刻回 200 → 入 queue 處理。

進到 Notion 那段是這樣:

Queue Worker

Stripe event:拿 charge.succeeded / invoice.payment_succeeded

Function:抽 customer_id + amount + currency + 訂閱資訊

Notion:用 customer_id 查 Customer page(pipeline 1 已建立)

Notion:用 charge_id 查 Order page
  ├─ 找到 → PATCH(更新狀態)
  └─ 找不到 → POST(建立 Order page,relation 到 Customer)

關鍵:用 charge_id 而不是 invoice_id 當 External ID。一個 invoice 可能對應多次重試付款(每次有自己的 charge_id),用 invoice_id 會把第二次成功的付款蓋掉第一次失敗的紀錄。

Notion relation field 把 Order 關聯回 Customer 的兩種方法

方法 A:n8n 在建立 Order 時,先 query Customer database 拿到 page_id,寫進 Order 的 relation property。優點是同步當下就有 relation;缺點是每筆 Order 多一次 API call。

方法 B:先用 External ID 純文字寫進 Order,每天跑一次 batch 工作流補 relation(找 Order.customer_external_id 比對 Customer.External ID)。優點是同步本身快;缺點是 Order 進來後到 batch 跑完之間有空窗。

production 經驗:60 單以下的客戶用 A、60 單以上的用 B。原因是 A 的 API call 量會跟著訂單規模線性放大,B 是固定成本。

退款 / 訂閱續訂 / 失敗事件的狀態欄位設計

Order database 必有的狀態欄位:

PropertyType來源
StatusSelectsucceeded / refunded / failed / disputed / partial_refunded
Refund AmountNumbercharge.refunded 事件的 amount_refunded
Subscription PhaseSelectinitial / renewal / final / cancelled
Failed ReasonRich Textfailure_message
Dispute ReasonRich Textdispute 事件的 reason

Status 用 Select 而不是 Checkbox 的原因:狀態不是布林,是有限狀態機。partial_refundeddisputed 是兩種完全不同的 case,要分開追蹤。

退款不要修改原訂單的 amount,新增一條 Refund Amount,因為原始交易金額是會計憑證,不能被「修改」,只能被「沖銷」。會計部門看到原 amount 改了會抓狂。

pipeline 3:內容排程同步(Postiz / GA4 → Notion Content Calendar)

第三條把 Notion 升級成內容飛輪儀表板,把產出、排程、成效拉在一張表。

一張 Notion Content Calendar 同時管文章、社群、Lead Magnet

Calendar database 的 schema:

PropertyType來源
TitleTitle手動
TypeSelectArticle / FB Post / IG Carousel / Threads / Lead Magnet
PillarSelect對應品牌的 content pillar
StatusSelectplanned / drafting / scheduled / published / measured
Publish DateDaten8n 從 Postiz 同步
URLURL文章發布後 n8n 寫回
PageviewsNumberGA4 14 天後回填
Engagement RateNumberPostiz analytics 14 天後回填
CTRNumberGSC 14 天後回填
Related CustomerRelation連到 Customer database(如果這篇是寫給某個客戶問題)
Lead Magnet ConversionNumberD1 / GA4 conversion event

Type + Pillar 是兩個維度,不要混。Type 是「格式」(FB / IG / Article),Pillar 是「主題分類」(自動化教學 / 行業案例 / 工具評測),用兩個 select 才能做交叉分析。

GA4 表現回填到 Notion

GA4 Data API 拿數據的 n8n workflow:

Schedule Trigger (每天 09:00)

Notion:查 Calendar 中 Status=published 且 Publish Date >= 14 天前的記錄

SplitInBatches (size 5)

GA4:用 path 查該文章 14 天內的 pageviews + bounceRate + avgEngagementTime

Notion:PATCH 該 page,寫回 Pageviews / Engagement

Function:判斷 Status 是否要從 published 轉成 measured

Notion:PATCH Status

回填一定要等 14 天以上,因為前 7 天的 GA4 數據還在採樣 + reprocessing。回填太早數字會跳,後面再修又會被同事覺得「這數字不可靠」,整套 SoT 信用就崩了。

內容狀態流:planned → drafting → scheduled → published → measured

五段狀態的判斷規則:

  • planned:Calendar 有條目,但沒人開始寫
  • drafting:Notion page 內容字數 > 100(或人工標記)
  • scheduled:Postiz / Astro repo 已建立 post,n8n 自動更新
  • published:Postiz status=published 或文章 URL 200,n8n 自動更新
  • measured:發布 14 天後,GA4 數據已回填,n8n 自動更新

measured 是篩出「可以做覆盤」的條目用的,每月底跑覆盤就 filter Status=measured AND Publish Date >= 上月 1 號,自動拿到上個月所有可以分析的內容。

雙向同步的衝突解決:哪邊是 source of truth

雙向同步是 production 最大地雷。資料工程的鐵則:每一個 entity 永遠只能有一個 SoT,其他都是 mirror。

timestamp-based last-write-wins vs 欄位級分權

簡單做法:每筆記錄存 last_modified_at + last_modified_source,誰晚改誰贏。問題是當 HubSpot 和 Notion 同時改同一筆,兩邊都覺得自己是後改的(時鐘漂移、時區差),會打架。

production 解法:欄位級分權。明確定義哪些欄位由誰當 SoT,超出範圍直接 reject:

欄位SoT反向同步
Customer.Name / EmailHubSpotNotion 不可改
Customer.StageHubSpotNotion 改了要送回 HubSpot
Customer.NotesNotion不送回 HubSpot
Customer.OwnerNotion送回 HubSpot
Order.amount / statusStripeNotion 唯讀
Order.Internal NoteNotion不送回 Stripe

寫死規則比 timestamp 邏輯穩 10 倍。

deletion 同步是地雷 — 用 archive 取代 delete

不要把「Notion 刪 page」翻譯成「HubSpot 刪 contact」。原因:

  • 員工誤刪 Notion page 太常見
  • HubSpot / Stripe 刪除是 GDPR 等級操作,不可逆
  • 客戶資料一旦誤刪,連 backup 復原都得跑 24 小時流程

正確姿勢:所有 Customer / Order 加 Archived checkbox,要「刪除」就打勾。每天跑一次 cleanup workflow 把 Archived=true AND archived_at > 30 天 的記錄 hard delete。30 天是緩衝期,給人類反悔。

衝突 log 寫進 Notion 一個獨立 database

開一個 Sync Conflicts database,每次 n8n 偵測到「兩邊都改了同一欄位」就寫一筆:

Property內容
EntityCustomer / Order 的 page link
Field衝突欄位名
HubSpot Value來源 1 的值
Notion Value來源 2 的值
Detected At時間
Resolved By解決衝突的人
Resolution採用哪邊

每週開會花 15 分鐘掃這張表,找出系統設計缺漏。production 跑半年內,衝突數應該從每週 30 筆掉到每週 < 3 筆,掉不下來代表規則設計還有問題。

10 個 production blueprint:照抄就能用

把上述三條 pipeline 變成可重用 blueprint,每個都已經在 n8nstart.cc 模板商城上架,購買後直接 import。

  1. 新訂單自動建立 onboarding task 給 CSM:Stripe checkout.session.completed → 建立 Notion Task page,relation 到 Customer,分配給 Owner
  2. 訂閱到期前 7 天自動寫客戶筆記 + Slack alert:Stripe Subscription 到期日 -7 天觸發 → Notion Customer page 加一條 Note → Slack DM 給 Owner
  3. HubSpot deal stage 變動同步:HubSpot webhook → Notion Customer.Stage 更新 → 內部 Slack 通知 sales lead
  4. 退款超過 NTD 10000 自動建立 escalation:Stripe charge.refunded 金額 >10000 → 建立 Notion Escalation page → email 給財務 + Slack alert
  5. 內容發布後 14 天 GA4 回填 + 自動歸檔:上面 pipeline 3 的完整版
  6. Lead Magnet 下載觸發 nurture sequence:D1 magnet_leads INSERT → Notion 建立 Lead page → 啟動 7 天 email 序列 + 5 天後 sales follow-up task
  7. 客戶 30 天未互動自動 churn risk 標記:每天 cron → Notion filter Last Touch < 30 天前 → 加 ChurnRisk tag → 推到 CSM weekly review
  8. 新文章發布自動同步到 Postiz 排程:Astro repo push → n8n 抓 frontmatter → Postiz 建立 FB/IG/Threads 排程 → 寫回 Notion Content Calendar
  9. 競品內容變動 alert:Notion 競品清單 → daily cron 抓對方 RSS → 有新文章 PATCH 進 Notion + Slack
  10. 月底 MRR 報表自動產出:Stripe 月底跑 → 算 MRR/Churn/Expansion → 寫進 Notion Monthly Report page + 寄給管理層

每個 blueprint 都遵守一條原則:Notion 是 human-readable mirror,原始系統才是 SoT。寫入 Notion 隨便寫,反向寫回原始系統嚴格驗證。

30 天落地節奏

從零開始把這套 SoT 鋪起來的節奏:

任務完成標準
D+0開 Notion workspace + 3 個 database(Customer / Order / Calendar)+ Schema 鎖死property 全部建好 + External ID 設成 unique view
D+3n8n self-host + Notion integration token + 基礎 workflow 框架Schedule Trigger 跑 1 筆測試 → Notion 出現一筆記錄
D+7Pipeline 1 客戶同步上線 + 跑 60 小時穩定HubSpot 100 筆 contacts 全部進 Notion,零 duplicate
D+14Pipeline 2 訂單同步上線 + 完成 webhook 驗簽 + 去重Stripe test event 重送 16 次,Notion 只有 1 筆
D+21Pipeline 3 內容排程同步上線 + GA4 回填Calendar 有上週發布的內容自動標 measured
D+28衝突 log database + cleanup workflow + Archive 機制故意製造衝突,Sync Conflicts database 有紀錄
D+30dashboard 化:在 Notion 建 5 個 view 給不同角色(CSM/Sales/Marketing/Boss)每個角色 30 秒內找到自己要的數字

收斂三個指標:

  • 同步成功率 > 99.5%(DLQ 進場率 < 0.5%)
  • 衝突率 < 1%(每 100 筆同步 < 1 次衝突)
  • 老闆查月 MRR 時間 < 10 秒

三個指標達標,Notion 就真的變成 SoT。沒達標代表設計還有缺,回頭看上面對應段落。

常見問題

Q:Notion API rate limit 3 req/sec,公司一天 1 萬筆訂單會卡死,怎麼辦? 答:先做佇列(Redis-backed queue),再把 batch size 拉小 + 不要併發。10000 筆 / 3 req/sec ≈ 56 分鐘,跑得完。如果業務真的需要 < 1 分鐘 latency,Notion 不是對的工具,改用 Retool 或自建 dashboard。

Q:Notion sync 到一半被人手動改了,會被 n8n 蓋掉嗎? 答:取決於同步邏輯。簡單版的 PATCH 會直接蓋;正確做法是先 GET 比對 hash,沒變才寫;變了就觸發衝突 log。production 工作流必須有這層 guard,不然 CSM 的筆記隨時被覆蓋。

Q:Notion 有沒有自家的「自動化」可以取代 n8n? 答:Notion automation 適合 Notion 內部觸發(property 變了 → 改另一個 property),但跨系統整合(Stripe webhook → Notion)能力很弱,連 webhook signature 驗證都沒有。n8n 是補這塊的最佳工具。實際組合:n8n 跨系統 + Notion automation 內部觸發。

Q:我們已經用 Airtable 一段時間了,要不要全切換到 Notion? 答:不一定。Airtable 跑大量結構化資料(萬筆以上)效能比 Notion 好;Notion 強在「人看的介面 + 內嵌文件」。建議混用:交易型資料留 Airtable / Postgres,給人看的儀表板放 Notion,n8n 在中間同步。SoT 的概念跟工具無關。

把這套 SoT 鋪好後最大的改變不是省時間,是「老闆問問題有單一答案」。中小企業最痛的不是缺工具,是工具太多沒對齊。n8n + Notion 不會讓你變大公司,但會讓你的小團隊跑得像一個整體。