Branch8

台灣電商品牌會員日自動化 workflow 設定教學:HubSpot 實戰

Matt Li
November 10, 2026
13 mins read
台灣電商品牌會員日自動化 workflow 設定教學:HubSpot 實戰

Key Takeaways

  • 把會員等級與消費邏輯沉澱為自訂屬性,workflow 只做流程
  • 用 Active List 動態分群,並永遠掛上 suppression 排除名單
  • Custom code action 有 20 秒上限,非關鍵動作改走非同步佇列
  • 台灣以 LINE 為主通道,跨市場只換通道分支、不複製整條 workflow
  • LLM 放在批次與分析層,不要放進發送關鍵路徑

會員日自動化的核心是:在 HubSpot 建立會員等級與消費行為的自訂屬性、用 Active List 動態分群,再以一條主 workflow 串接 T-7 預告、T-0 發券、T+2 提醒,並透過 custom code action 呼叫電商平台與 LINE Messaging API 完成發券與推播。

為什麼台灣電商的「會員日」特別難自動化

台灣電商的會員日不是單一檔期,而是三種活動疊在一起:品牌固定的每月會員日、會員個人生日月、以及等級續會/升等的臨界點。這三件事的觸發邏輯完全不同,但行銷團隊往往用同一份 EDM 名單硬打,結果是高價值會員被低折扣訊息稀釋,低活躍會員則收到看不懂的升等通知。

規模上,依經濟部統計處「零售業網路銷售額」統計,台灣零售業網路銷售額已達新台幣 4,800 億元量級,而 LINE 台灣官方公布的台灣月活躍用戶數約 2,100 萬以上——這代表會員溝通的主戰場不在 Email,而在 Email 與 LINE 的組合。HubSpot 原生不支援 LINE,所以本教學的關鍵段落會放在 custom code action 如何把 HubSpot 當作決策中樞、LINE 當作遞送通道。

這套架構同樣適用於跨境情境:同一條 workflow 可依 country 或 brand_market 屬性分流,台灣走 LINE、香港走 WhatsApp、澳洲與英國走 Email + SMS。決策邏輯只寫一次,通道在最後一哩才分岔。

開始前你需要準備什麼

在動手之前,先確認以下條件,否則做到步驟四會卡住:

  1. HubSpot Marketing Hub Professional 以上。Workflows 是 Professional 起跳的功能;依 HubSpot 官方產品說明,Professional 方案 workflow 數量上限為 300 條、Enterprise 為 1,000 條。Custom code action(可寫 Node.js 或 Python)則僅限 Operations Hub Professional/Enterprise。
  2. Private App access token。到 Settings → Integrations → Private Apps 建立,至少勾選 crm.objects.contacts.read/write、crm.objects.deals.read、crm.schemas.contacts.write。
  3. 電商平台的 Admin API 權限。Shopify 需 Admin GraphQL API 的 read_customers / write_discounts;91APP、Cyberbiz、SHOPLINE 等台灣常見平台則需確認其 Open API 是否提供折價券建立端點,若無則退回「預先產券、程式配券」模式。
  4. LINE Official Account(認證帳號)+ Messaging API channel,取得 Channel access token。注意 LINE 的推播訊息採用量計費,免費方案額度有限,這會直接影響你 workflow 的發送頻率設計。
  5. 個資合規基礎。台灣《個人資料保護法》要求蒐集時明確告知利用目的與期間,行銷利用須提供免費拒絕方式。HubSpot 的 Subscription Types 要同時建立「會員電子報」與「活動促銷」兩種,並把 LINE 的 opt-out 狀態回寫到 HubSpot 的自訂屬性,否則你會有一條退訂了 Email 卻還在收 LINE 的客戶。

Ready to Transform Your Ecommerce Operations?

Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.

步驟一:設計會員日需要的自訂屬性

不要把邏輯寫在 workflow 裡,要把邏輯沉澱成屬性。這是後續可維護性的分水嶺。

最小可用的屬性集合(contact object):

  • member_tier — 下拉式(Bronze / Silver / Gold / Platinum)
  • member_join_date — 日期
  • member_birthday_month — 數字(1–12),用月份而非完整生日,避免不必要的敏感資料儲存
  • last_order_date — 日期
  • ltv_12m — 數字,滾動 12 個月消費額
  • tier_expiry_date — 日期,等級到期日
  • member_day_coupon_code — 單行文字,本期發出的券碼
  • member_day_coupon_issued_at — 日期時間,防重複發券的關鍵
  • line_user_id — 單行文字
  • line_marketing_opt_in — 核取方塊

用 API 一次建立(以 Node.js + Private App token 為例):

1curl -X POST \
2 'https://api.hubapi.com/crm/v3/properties/contacts' \
3 -H "Authorization: Bearer $HUBSPOT_PRIVATE_APP_TOKEN" \
4 -H 'Content-Type: application/json' \
5 -d '{
6 "name": "member_day_coupon_issued_at",
7 "label": "會員日券發送時間",
8 "groupName": "membership",
9 "type": "datetime",
10 "fieldType": "date"
11 }'

預期回應為 HTTP 201,body 內含 "name": "member_day_coupon_issued_at"。若回 409,代表屬性已存在;若回 403,回頭檢查 Private App 是否勾選 crm.schemas.contacts.write。

實務建議:member_tier 一定要用下拉式而非文字欄位。曾經在一個東南亞多品牌零售集團的 HubSpot 導入中,因為等級欄位是自由文字,同一個等級出現了 Gold、gold、GOLD 三種寫法,導致分群名單漏掉三分之一的人——這類問題在資料層修比在 workflow 層補救便宜太多。

步驟二:把電商訂單資料接進 HubSpot

會員日的所有判斷都依賴消費行為,所以訂單同步是前置工程。兩種常見做法:

方法 A:平台原生整合(建議先試)

Shopify 有官方 HubSpot App,可同步客戶與訂單並自動建立 Orders 物件。SHOPLINE、Cyberbiz 等平台則多半需走 Zapier / Make 或自建中介層。原生整合的限制是欄位對應固定,ltv_12m 這種滾動計算欄位通常還是要自己算。

方法 B:自建 webhook 中介層

訂單成立時由電商平台打到你的 endpoint,再由中介層計算衍生欄位後寫回 HubSpot。以 Cloudflare Workers 或 AWS Lambda 接收為例:

1// 訂單 webhook → 計算滾動 12 個月 LTV → 回寫 HubSpot
2const HUBSPOT_API = 'https://api.hubapi.com';
3
4export async function handleOrderWebhook(order, env) {
5 const email = order.customer.email.toLowerCase().trim();
6
7 // 1. 以 email 找到 contact
8 const search = await fetch(`${HUBSPOT_API}/crm/v3/objects/contacts/search`, {
9 method: 'POST',
10 headers: {
11 Authorization: `Bearer ${env.HUBSPOT_TOKEN}`,
12 'Content-Type': 'application/json',
13 },
14 body: JSON.stringify({
15 filterGroups: [{
16 filters: [{ propertyName: 'email', operator: 'EQ', value: email }],
17 }],
18 properties: ['ltv_12m', 'member_tier'],
19 limit: 1,
20 }),
21 }).then(r => r.json());
22
23 if (!search.total) return { status: 'contact_not_found' };
24
25 const contact = search.results[0];
26 const newLtv = Number(contact.properties.ltv_12m || 0) + Number(order.total_price);
27
28 // 2. 回寫
29 await fetch(`${HUBSPOT_API}/crm/v3/objects/contacts/${contact.id}`, {
30 method: 'PATCH',
31 headers: {
32 Authorization: `Bearer ${env.HUBSPOT_TOKEN}`,
33 'Content-Type': 'application/json',
34 },
35 body: JSON.stringify({
36 properties: {
37 ltv_12m: newLtv.toFixed(0),
38 last_order_date: order.created_at.slice(0, 10),
39 },
40 }),
41 });
42
43 return { status: 'ok', contactId: contact.id, ltv_12m: newLtv };
44}

注意 API 速率限制。依 HubSpot 官方 Usage Guidelines,Professional/Enterprise 的 Private App 預設約為每 10 秒 190 次請求、每日 500,000 次(未購買 API limit increase 時數值更低)。大檔期時訂單 webhook 會爆量,務必加上佇列與指數退避重試:

1async function withRetry(fn, max = 5) {
2 for (let i = 0; i < max; i++) {
3 const res = await fn();
4 if (res.status !== 429) return res;
5 await new Promise(r => setTimeout(r, 2 ** i * 500));
6 }
7 throw new Error('HubSpot rate limit exceeded after retries');
8}

滾動 LTV 不要只用累加。正確做法是每晚跑一次批次,重新計算過去 365 天的訂單總和並覆寫,避免累加法在退貨、取消單時永久失真。

Ready to Transform Your Ecommerce Operations?

Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.

步驟三:用 Active List 建立會員日分群

在 HubSpot 建立 Active List(動態名單),而非 Static List。動態名單會自動隨屬性變動進出,這正是會員日每月重跑所需要的。

建立四組名單:

  • MD – 本月生日會員:member_birthday_month equals {{ 當月 }} AND line_marketing_opt_in 或 Email 訂閱任一為真
  • MD – 高價值待喚醒:ltv_12m is greater than 20000 AND last_order_date is more than 90 days ago
  • MD – 升等臨界:member_tier is Silver AND ltv_12m is between 25000 and 29999(假設 Gold 門檻為 30,000)
  • MD – 排除名單:member_day_coupon_issued_at is less than 30 days ago OR hs_email_optout is true

最後一組是整套設計的保險絲。台灣電商最常見的客訴之一就是同一個人在一週內收到三張不同的會員日券,而每張條件還不一樣。排除名單解決的是這個問題。

步驟四:設定會員日主 workflow 的時間軸

進 Automation → Workflows → Create workflow → Contact-based,enrollment trigger 選「Contact is member of list: MD – 本月生日會員」。

建議的節奏(以會員日為 T-0):

  1. T-7 預告:發送 Marketing Email「您的專屬會員日即將開始」,內容只預告、不給券。目的是拉高 T-0 的開信基線。
  2. Delay until 設定為月份中的固定日期(HubSpot 的 Delay until a specific day or date action),不要用「delay 7 days」,否則會因 enrollment 時間不同而散開。
  3. T-0 分支:加一個 if/then branch,以 member_tier 分流。Gold/Platinum 走 custom code 發放高面額券 + LINE 推播;Bronze/Silver 走標準券 + Email。
  4. T-0 寫入 member_day_coupon_issued_at = 現在時間。這一步必須在發券動作之後、且在所有分支都執行,否則排除名單會失效。
  5. T+2 未使用提醒:branch 判斷 member_day_coupon_used is not true,若未使用則推送一則 LINE 訊息。
  6. T+5 結束:workflow 走到 goal 或結束。

Settings 裡務必確認三件事:

  • Enrollment:不要勾選「Allow contacts to re-enroll」除非你同時設了 suppression,否則資料修正會導致重複入列。
  • Execution schedule:設定為台北時間的工作時段(例如 10:00–20:00),避免 HubSpot 依 portal 預設時區在半夜推播。跨市場品牌請為每個市場建獨立 workflow,而非在同一條裡混時區。
  • Suppression lists:把「MD – 排除名單」掛上去。

Ready to Transform Your Ecommerce Operations?

Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.

步驟五:用 custom code action 串接發券與 LINE 推播

HubSpot 的 custom code action(Operations Hub Professional 以上)支援 Node.js 與 Python,執行時間上限為 20 秒,且必須在 20 秒內回傳 callback。超時會直接失敗且不重試,所以不要在裡面做長鏈路呼叫。

以下是 Shopify 建立折扣碼 + LINE 推播的合併範例(Node.js 20):

1const axios = require('axios');
2
3exports.main = async (event, callback) => {
4 const { hs_object_id, member_tier, line_user_id, firstname } = event.inputFields;
5
6 // 依等級決定面額
7 const tierValue = { Platinum: 500, Gold: 300, Silver: 150, Bronze: 100 };
8 const amount = tierValue[member_tier] || 100;
9 const code = `MD${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}-${hs_object_id}`;
10
11 // 1. Shopify Admin GraphQL:建立單人專屬折扣碼
12 const mutation = `
13 mutation($basic: DiscountCodeBasicInput!) {
14 discountCodeBasicCreate(basicCodeDiscount: $basic) {
15 codeDiscountNode { id }
16 userErrors { field message }
17 }
18 }`;
19
20 const shopifyRes = await axios.post(
21 `https://${process.env.SHOP_DOMAIN}/admin/api/2024-10/graphql.json`,
22 {
23 query: mutation,
24 variables: {
25 basic: {
26 title: `MemberDay-${hs_object_id}`,
27 code,
28 startsAt: new Date().toISOString(),
29 usageLimit: 1,
30 customerSelection: { all: true },
31 customerGets: {
32 value: { discountAmount: { amount, appliesOnEachItem: false } },
33 items: { all: true },
34 },
35 },
36 },
37 },
38 { headers: { 'X-Shopify-Access-Token': process.env.SHOPIFY_TOKEN } }
39 );
40
41 const errors = shopifyRes.data?.data?.discountCodeBasicCreate?.userErrors || [];
42 if (errors.length) {
43 return callback({ outputFields: { status: 'coupon_failed', error: errors[0].message } });
44 }
45
46 // 2. LINE Messaging API push(僅在有 userId 且已 opt-in 時)
47 if (line_user_id) {
48 await axios.post(
49 'https://api.line.me/v2/bot/message/push',
50 {
51 to: line_user_id,
52 messages: [{
53 type: 'text',
54 text: `${firstname} 您好,您的會員日專屬 ${amount} 元折價券已發送:${code}(限用一次,7 日內有效)`,
55 }],
56 },
57 { headers: { Authorization: `Bearer ${process.env.LINE_CHANNEL_TOKEN}` } }
58 );
59 }
60
61 callback({
62 outputFields: {
63 status: 'ok',
64 coupon_code: code,
65 coupon_amount: amount,
66 },
67 });
68};

設定要點:

  • Secrets:SHOPIFY_TOKEN、LINE_CHANNEL_TOKEN 在 custom code action 的 Secrets 區塊新增,不要硬編在程式碼裡。
  • Input fields:把 hs_object_id、member_tier、line_user_id、firstname 加入,否則 event.inputFields 會是空的。
  • Output fields:宣告 status(string)、coupon_code(string)、coupon_amount(number),之後才能在下一步用 branch 判斷,並把 coupon_code 寫回 member_day_coupon_code 屬性。
  • 在 custom code 後面接一個 if/then branch:status equals ok 才走發信路徑;否則導向內部通知 workflow,把失敗名單丟到一個 Static List 供人工處理。

步驟六:加上抑制規則與 A/B 測試

自動化上線後最容易出事的不是發不出去,而是發太多。三條抑制規則建議一律套用:

  1. 頻率上限:同一 contact 30 天內最多收到一次會員日類型推播。靠 member_day_coupon_issued_at 判斷,寫在 suppression list。
  2. 通道去重:若 LINE 推播在 status = ok 時成功,就跳過 T-0 的 Email。HubSpot 可用 branch 判斷 custom code 的 output field 達成,這能同時省下 LINE 與 Email 的成本。
  3. 檔期衝突鎖:建立一個 campaign_lock_until 日期屬性,任何大型檔期 workflow 寫入後,會員日 workflow 以 campaign_lock_until is less than today 為入列條件。

A/B 測試方面,HubSpot workflow 內可用 Randomly split 分流。實用的測試不是標題黨對比,而是結構性變數:T-7 預告 vs 無預告、券金額 vs 免運、LINE 優先 vs Email 優先。把 workflow 的分支結果寫進一個 member_day_variant 屬性,之後在報表裡就能用這個維度切。

Ready to Transform Your Ecommerce Operations?

Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.

步驟七:上線前的測試檢查清單

不要用真實客戶測試。做法是:

  1. 建立 5 個測試 contact,email 使用 + 別名(例如 [email protected]),分別覆蓋四個等級與一個無 line_user_id 的情況。
  2. 把 workflow 的 enrollment 暫時改成「Contact is member of list: QA – Member Day Test」。
  3. 開啟 workflow,觀察每個 contact 的 Action logs(在 contact timeline 上可見),確認:
  • 券碼確實在 Shopify Admin 後台出現
  • member_day_coupon_issued_at 有寫入
  • 無 line_user_id 的 contact 不會卡在 custom code 失敗
  1. 用 LINE 官方帳號管理後台確認推播已送達,並檢查訊息用量是否符合預期。
  2. 把排除名單故意套在其中一個測試 contact 上,確認它沒有入列——這是最常被略過、也最常出包的一項。
  3. 全部通過後才把 enrollment trigger 換回正式名單,並先以 50 人的小名單跑第一輪。

常見錯誤與排除方法

Contact 沒有入列 workflow

先看 Active List 的成員數。若名單是空的,九成是屬性值大小寫或空白不一致(Gold ` 帶尾端空格是經典案例)。用 HubSpot 的 Operations Hub `Format data action 或在匯入前統一清洗。另一個可能是 suppression list 誤殺——把 contact 丟進 list 詳情頁的「Why is this contact in this list?」檢視。

Custom code action 回 TIMEOUT

20 秒上限。若你在同一段程式裡依序呼叫 Shopify、LINE、再回寫一次 HubSpot,很容易超時。解法是把非即時的動作(例如寫入 CDP、推到資料倉儲)改為丟訊息到佇列,由外部服務非同步處理,custom code 只負責關鍵路徑。

LINE push 回 400 Invalid user ID

line_user_id 必須是以 U 開頭的 33 字元字串,不是 LINE ID(@開頭的那個)。若你是透過 LINE Login 或官方帳號綁定取得,確認綁定流程寫回的是 userId 而非 displayName。另外,user 封鎖官方帳號後 push 也會失敗,需在 webhook 接收 unfollow 事件時把 line_marketing_opt_in 設為 false。

折扣碼重複建立

若 workflow 設定允許 re-enrollment,同一個 contact 可能二次觸發。除了 suppression list,也在 custom code 內加冪等檢查:以 MD{YYYYMM}-{contactId} 當作券碼格式,Shopify 會因 code 重複回 userErrors,這時直接回傳既有券碼而非報錯。

報表數字對不上

HubSpot 的 workflow performance 算的是「發送」,電商後台算的是「使用」。兩邊要對得起來,必須在訂單成立時把使用的折扣碼回寫到 contact 的 member_day_coupon_used。沒有這條回寫,你永遠無法算出真正的會員日 ROI。

Ready to Transform Your Ecommerce Operations?

Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.

讓 AI 輔助 workflow 維運,而不是取代它

2026 年值得加進這套架構的一層,是用 LLM 處理「判斷類」而非「發送類」工作。三個已經可落地的用法:

  • 文案變體生成:在 custom code 之外,用一個排程腳本呼叫 LLM API,依 member_tier 與近期瀏覽品類生成 3 組 LINE 推播文案,寫入 HubSpot 的 Custom Object,再由 workflow 取用。人工只做審稿,不做初稿。
  • 異常偵測:每日把 workflow 的 enrollment 數、custom code 失敗率餵給一個簡單的判讀 prompt,偏離移動平均一定幅度就發 Slack 告警。這比在 HubSpot 裡設一堆靜態閾值更耐用。
  • 退訂與客訴歸因:把客服工單摘要與會員日發送紀錄 join 起來,讓 LLM 分類退訂原因。頻率過高、折扣不相關、通道錯誤——這三類的解法完全不同。

要強調的是:LLM 不應該放在發送的關鍵路徑上。延遲不可預測、輸出不確定,放進 20 秒上限的 custom code 裡是在自找麻煩。把它放在批次層、審核層、分析層。

跨市場複製這套架構時該調整什麼

一個在台灣跑順的會員日 workflow,要複製到香港、新加坡、澳洲時,需要改的不是邏輯,是四個變數:

  • 通道:台灣 LINE 為主;香港 WhatsApp Business API;新加坡 WhatsApp + Email 並重;澳洲與英國 Email + SMS。把通道抽象成 custom code 裡的 channel 分支,而非複製整條 workflow。
  • 時區與執行視窗:HubSpot portal 只有一個預設時區。多市場請為每個市場建獨立 workflow,各自設 execution schedule。
  • 合規:台灣《個資法》、香港《個人資料(私隱)條例》、新加坡 PDPA、歐盟 GDPR 對「同意」的定義與記錄要求不同。同意來源與時間戳要存成屬性,不是存在行銷人員的記憶裡。
  • 幣別與券面額:不要用同一個 coupon_amount 數字欄位跨幣別,加一個 currency 屬性,或直接用百分比折扣避開匯率問題。

在為一間跨越港、台、星三地的多品牌零售集團建置 HubSpot 時,最花時間的往往不是 workflow 本身,而是把三地各自長出來的會員等級規則收斂成一套共用的屬性定義。技術工程兩週能做完,資料治理的共識通常才是主要路徑。

Ready to Transform Your Ecommerce Operations?

Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.

讓這套架構真正跑起來

Branch8 在香港、台灣、新加坡、澳洲等地有在地交付團隊,專注於 HubSpot、Salesforce 與 CDP 的導入與跨境整合——從屬性設計、電商資料串接到 LINE/WhatsApp 通道對接。如果你正在規劃會員生命週期自動化,或手上的 workflow 已經多到沒人敢改,歡迎與我們聊聊你的現況。

Sources

FAQ

Workflows 功能需要 Marketing Hub Professional 以上;若要使用 custom code action 串接 Shopify 折價券或 LINE Messaging API,則需額外的 Operations Hub Professional 或 Enterprise。僅有 Starter 方案時,只能使用較基礎的 email 自動化與表單後續動作。

About the Author

Matt Li

Co-Founder & CEO, Branch8 & Second Talent

Matt Li is Co-Founder and CEO of Branch8, a Y Combinator-backed (S15) Adobe Solution Partner and e-commerce consultancy headquartered in Hong Kong, and Co-Founder of Second Talent, a global tech hiring platform ranked #1 in Global Hiring on G2. With 12 years of experience in e-commerce strategy, platform implementation, and digital operations, he has led delivery of Adobe Commerce Cloud projects for enterprise clients including Chow Sang Sang, HomePlus (HKBN), Maxim's, Hong Kong International Airport, Hotai/Toyota, and Evisu. Prior to founding Branch8, Matt served as Vice President of Mid-Market Enterprises at HSBC. He serves as Vice Chairman of the Hong Kong E-Commerce Business Association (HKEBA). A self-taught software engineer, Matt graduated from the University of Toronto with a Bachelor of Commerce in Finance and Economics.