Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/campaign-response-kept-on-unsubscribe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hotcrm": patch
---

**A campaign member who responded and then unsubscribes still counts as a response.** Before, moving a member from *Responded* or *Converted* to *Unsubscribed* cleared **Has Responded** and **Response Date**, and the campaign's **Number of Responses** counted members by status, so every unsubscribe lowered the campaign's **Response Rate %**. Now the member keeps **Has Responded** and the original **Response Date** when they unsubscribe, and **Number of Responses** counts members who ever responded (**Has Responded**), so the response rate is "ever responded". Resetting a member to *Sent* still clears both. The demo data now includes one member who responded and later unsubscribed. The Marketing Manual and the Campaigns and Campaign Members docs say so in English and Chinese.
8 changes: 4 additions & 4 deletions content/docs/marketing/campaign-members.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The member status is the response lifecycle, and every value on it has something
| 🟣 **Converted** | Their lead went on to become a customer | Automatic, when that lead is converted |
| 🔴 **Unsubscribed** | They asked to stop hearing from you | A user who may edit campaign members, on the member record |

These four are not a ladder that only climbs. Most members stay at *Sent*; one who answers moves to *Responded*, and a member still at *Sent* or *Responded* whose lead is later converted is promoted to *Converted* for you. Moving a member back — a mis-click corrected, or a reset to *Sent* for a re-send — clears the response stamp with it. An *Unsubscribed* member is never promoted by that conversion sweep: an opt-out is not overwritten by a marketing outcome.
These four are not a ladder that only climbs. Most members stay at *Sent*; one who answers moves to *Responded*, and a member still at *Sent* or *Responded* whose lead is later converted is promoted to *Converted* for you. Moving a member back — a mis-click corrected, or a reset to *Sent* for a re-send — clears the response stamp with it. Unsubscribing a member who had responded does not: the response stays on the member and still counts as one of the campaign's responses. An *Unsubscribed* member is never promoted by that conversion sweep: an opt-out is not overwritten by a marketing outcome.

## Why both lead and contact?

Expand All @@ -56,7 +56,7 @@ If a lead is later converted to a contact, the existing campaign memberships sta
| Added Date | When the person was enrolled — stamped automatically the moment the membership is saved, whichever of the three ways above created it, and read-only afterwards |
| Status | Where the person got to (the four above) |
| Response Date | When they responded, stamped the first time they reach a responded status |
| Has Responded | The yes/no shortcut, kept in step with *Status* for you — *Converted* counts as responded |
| Has Responded | Whether the person ever responded, kept for you — *Converted* counts as responded, a reset to *Sent* clears it, and a member who responded keeps it after unsubscribing |

## What is tracked, and what is not

Expand All @@ -75,7 +75,7 @@ The campaign detail page rolls up its members:

```
Sent = every member of the campaign
Responses = members at Responded or Converted
Responses = members who ever responded (Has Responded), unsubscribed ones included
Response rate = Responses ÷ Sent, as a percentage
```

Expand All @@ -90,7 +90,7 @@ On the campaign detail page, under the **Related** tab, in a panel titled **Camp
Two things readers arrive expecting, and where they really are:

- There is no *Members* tab. Campaign membership is one panel among the campaign's other related records on the shared *Related* tab.
- There are no saved member list views — not *All Members*, *Responded*, *Unsubscribed* or *Converted to Opportunity*. Campaign Member ships no list views at all, and a related-list panel would not read them if it did: the panel's columns are curated on the campaign link itself, never from a view. Nothing ships that narrows the panel to one status, and no report ships over Campaign Member either, so "everyone who responded" is a number on the campaign rather than a list you can open: see [How the metrics roll up](#how-the-metrics-roll-up), where the response rate is computed live from member status.
- There are no saved member list views — not *All Members*, *Responded*, *Unsubscribed* or *Converted to Opportunity*. Campaign Member ships no list views at all, and a related-list panel would not read them if it did: the panel's columns are curated on the campaign link itself, never from a view. Nothing ships that narrows the panel to one status, and no report ships over Campaign Member either, so "everyone who responded" is a number on the campaign rather than a list you can open: see [How the metrics roll up](#how-the-metrics-roll-up), where the response rate is computed live from the members' responses.

## Tips for marketers

Expand Down
8 changes: 4 additions & 4 deletions content/docs/marketing/campaign-members.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ description: 加入每个营销活动的线索和联系人,以及如何跟踪
| 🟣 **已转化** | 其线索后来成为了客户 | 该线索转化时自动写入 |
| 🔴 **已退订** | 他们要求不再收到联系 | 可以编辑营销活动成员的用户,在成员记录上设置 |

这四个取值并不是一部只升不降的阶梯。大多数成员停在*已发送*;作出回应的移到*已响应*;仍处于*已发送*或*已响应*、其线索后来转化的成员会被自动提升为*已转化*。把成员改回去——纠正一次误点,或为了重发而重置回*已发送*——会连同响应时间戳一起清除。*已退订*的成员永远不会被那次转化扫描提升:退订不会被一个营销结果覆盖掉。
这四个取值并不是一部只升不降的阶梯。大多数成员停在*已发送*;作出回应的移到*已响应*;仍处于*已发送*或*已响应*、其线索后来转化的成员会被自动提升为*已转化*。把成员改回去——纠正一次误点,或为了重发而重置回*已发送*——会连同响应时间戳一起清除。把一个已经响应过的成员设为*已退订*则不会:响应留在成员上,仍算作营销活动的一次响应。*已退订*的成员永远不会被那次转化扫描提升:退订不会被一个营销结果覆盖掉。

## 为什么同时支持线索和联系人?

Expand All @@ -56,7 +56,7 @@ description: 加入每个营销活动的线索和联系人,以及如何跟踪
| Added Date | 该人加入的时间——无论通过上面三种方式中的哪一种加入,都在保存成员记录的那一刻自动写入,之后只读 |
| Status | 该人走到了哪一步(见上文四种状态) |
| Response Date | 他们响应的时间,在首次进入已响应状态时打上 |
| Has Responded | 是/否的快捷标识,由系统与*状态*保持一致——*已转化*同样算作已响应 |
| Has Responded | 此人是否曾经响应过,由系统维护——*已转化*同样算作已响应;重置回*已发送*会清除它;响应过的成员退订后仍保留它 |

## 什么被跟踪,什么没有

Expand All @@ -75,7 +75,7 @@ description: 加入每个营销活动的线索和联系人,以及如何跟踪

```
Sent = 该营销活动的全部成员
Responses = 处于 Responded 或 Converted 的成员
Responses = 曾经响应过的成员(Has Responded),含后来退订的
Response rate = Responses ÷ Sent,以百分比表示
```

Expand All @@ -90,7 +90,7 @@ Response rate = Responses ÷ Sent,以百分比表示
读者常带着两个预期过来,它们真正的落点是:

- **没有 *Members* 选项卡。** 成员面板只是活动在共用的 *Related* 选项卡上的关联记录面板之一。
- **没有任何成员列表视图** —— *All Members*、*Responded*、*Unsubscribed*、*Converted to Opportunity* 都不存在。Campaign Member 对象一个列表视图都没有;即便有,关联列表面板也不读子对象的列表视图:面板的列是在活动关联字段上直接定好的,从来不来自视图。产品里没有任何东西能把这个面板按状态筛选,也没有面向 Campaign Member 的报表,所以「所有响应过的人」是活动上的一个**数字**而不是一份可以打开的名单——见上文《指标如何汇总》一节,那里的响应率由成员状态实时算出。
- **没有任何成员列表视图** —— *All Members*、*Responded*、*Unsubscribed*、*Converted to Opportunity* 都不存在。Campaign Member 对象一个列表视图都没有;即便有,关联列表面板也不读子对象的列表视图:面板的列是在活动关联字段上直接定好的,从来不来自视图。产品里没有任何东西能把这个面板按状态筛选,也没有面向 Campaign Member 的报表,所以「所有响应过的人」是活动上的一个**数字**而不是一份可以打开的名单——见上文《指标如何汇总》一节,那里的响应率由成员的响应实时算出。

## 给营销人员的提示

Expand Down
8 changes: 4 additions & 4 deletions content/docs/marketing/campaign-members.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ description: 加入每個行銷活動的潛在客戶和聯絡人,以及如何
| 🟣 **已轉化** | 其潛在客戶後來成為了客戶 | 該潛在客戶轉化時自動寫入 |
| 🔴 **已退訂** | 他們要求不再收到聯絡 | 可以編輯行銷活動成員的使用者,在成員記錄上設定 |

這四個取值並不是一部只升不降的階梯。大多數成員停在*已發送*;作出回應的移到*已回應*;仍處於*已發送*或*已回應*、其潛在客戶後來轉化的成員會被自動提升為*已轉化*。把成員改回去——修正一次誤點,或為了重寄而重設回*已發送*——會連同回應時間戳一起清除。*已退訂*的成員永遠不會被那次轉化掃描提升:退訂不會被一個行銷結果覆蓋掉。
這四個取值並不是一部只升不降的階梯。大多數成員停在*已發送*;作出回應的移到*已回應*;仍處於*已發送*或*已回應*、其潛在客戶後來轉化的成員會被自動提升為*已轉化*。把成員改回去——修正一次誤點,或為了重寄而重設回*已發送*——會連同回應時間戳一起清除。把一個已經回應過的成員設為*已退訂*則不會:回應留在成員上,仍算作行銷活動的一次回應。*已退訂*的成員永遠不會被那次轉化掃描提升:退訂不會被一個行銷結果覆蓋掉。

## 為什麼同時支援潛在客戶和聯絡人?

Expand All @@ -58,7 +58,7 @@ description: 加入每個行銷活動的潛在客戶和聯絡人,以及如何
| Added Date | 該人加入的時間——無論透過上面三種方式中的哪一種加入,都在儲存成員記錄的那一刻自動寫入,之後唯讀 |
| Status | 該人走到了哪一步(見上文四種狀態) |
| Response Date | 他們回應的時間,在首次進入已回應狀態時打上 |
| Has Responded | 是/否的快捷標識,由系統與*狀態*保持一致——*已轉化*同樣算作已回應 |
| Has Responded | 此人是否曾經回應過,由系統維護——*已轉化*同樣算作已回應;重設回*已發送*會清除它;回應過的成員退訂後仍保留它 |

## 什麼被追蹤,什麼沒有

Expand All @@ -77,7 +77,7 @@ description: 加入每個行銷活動的潛在客戶和聯絡人,以及如何

```
Sent = 該行銷活動的全部成員
Responses = 處於 Responded 或 Converted 的成員
Responses = 曾經回應過的成員(Has Responded),含後來退訂的
Response rate = Responses ÷ Sent,以百分比表示
```

Expand All @@ -92,7 +92,7 @@ Response rate = Responses ÷ Sent,以百分比表示
讀者常帶著兩個預期過來,它們真正的落點是:

- **沒有 *Members* 索引標籤。** 成員面板只是活動在共用的 *Related* 索引標籤上的關聯記錄面板之一。
- **沒有任何成員清單檢視** —— *All Members*、*Responded*、*Unsubscribed*、*Converted to Opportunity* 都不存在。Campaign Member 物件一個清單檢視都沒有;即便有,關聯清單面板也不讀子物件的清單檢視:面板的欄位是在活動關聯欄位上直接定好的,從來不來自檢視。產品裡沒有任何東西能把這個面板按狀態篩選,也沒有面向 Campaign Member 的報表,所以「所有回應過的人」是活動上的一個**數字**而不是一份可以開啟的名單——見上文《指標如何彙總》一節,那裡的回應率由成員狀態即時算出。
- **沒有任何成員清單檢視** —— *All Members*、*Responded*、*Unsubscribed*、*Converted to Opportunity* 都不存在。Campaign Member 物件一個清單檢視都沒有;即便有,關聯清單面板也不讀子物件的清單檢視:面板的欄位是在活動關聯欄位上直接定好的,從來不來自檢視。產品裡沒有任何東西能把這個面板按狀態篩選,也沒有面向 Campaign Member 的報表,所以「所有回應過的人」是活動上的一個**數字**而不是一份可以開啟的名單——見上文《指標如何彙總》一節,那裡的回應率由成員的回應即時算出。

## 給行銷人員的提示

Expand Down
2 changes: 1 addition & 1 deletion content/docs/marketing/campaigns.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ For real-time campaigns (e.g., a webinar with a registration form), you can also
The numbers live on the campaign record itself — the counters and the response rate in *Performance*, the money and ROI in *Budget & ROI*. Every one of them is recomputed as members are enrolled or answer, as their leads convert, and as opportunities are attributed to the campaign:

- **Number Sent** — every member enrolled in the campaign, whatever their status.
- **Number of Responses** — members at *Responded* **or** *Converted*: a member whose lead converted answered too, and the counter says so.
- **Number of Responses** — members who ever responded: those at *Responded* **or** *Converted* (a member whose lead converted answered too), and a member who responded and later became *Unsubscribed* — an opt-out does not take the response back.
- **Response Rate %** — responses ÷ number sent, as a percentage. It is the only rate the campaign carries.
- **Number of Leads** — the distinct leads among those members.
- **Converted Leads** — how many of those leads have since been converted.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/marketing/campaigns.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ description: 规划、启动并衡量市场营销举措——电子邮件、网
这些数字就在营销活动记录本身上——各项计数与响应率在 *Performance* 部分,金额与 ROI 在 *Budget & ROI* 部分。它们会随着成员加入、成员响应、其线索转化、商机归因到该营销活动而重新计算:

- **Number Sent** — 加入该营销活动的全部成员,无论其状态为何。
- **Number of Responses** — 状态为*已响应* **或** *已转化*的成员:线索已转化的成员同样作出过响应,这个计数把他们算了进来。
- **Number of Responses** — 曾经作出响应的成员:状态为*已响应* **或** *已转化*的成员(线索已转化的成员同样作出过响应),以及先响应、后来变为*已退订*的成员——退订不会把那次响应收回。
- **Response Rate %** — 响应数 ÷ 发送数量的百分比。这是营销活动上唯一的一个“率”。
- **Number of Leads** — 这些成员中不重复的线索数。
- **Converted Leads** — 其中后来完成了转化的线索数。
Expand Down
2 changes: 1 addition & 1 deletion content/docs/marketing/campaigns.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ description: 規劃、啟動並衡量行銷舉措——電子郵件、網路研
這些數字就在行銷活動記錄本身上——各項計數與回應率在 *Performance* 部分,金額與 ROI 在 *Budget & ROI* 部分。它們會隨著成員加入、成員回應、其潛在客戶轉化、商機歸因到該行銷活動而重新計算:

- **Number Sent** — 加入該行銷活動的全部成員,無論其狀態為何。
- **Number of Responses** — 狀態為*已回應* **或** *已轉化*的成員:潛在客戶已轉化的成員同樣作出過回應,這個計數把他們算了進來。
- **Number of Responses** — 曾經作出回應的成員:狀態為*已回應* **或** *已轉化*的成員(潛在客戶已轉化的成員同樣作出過回應),以及先回應、後來變為*已退訂*的成員——退訂不會把那次回應收回。
- **Response Rate %** — 回應數 ÷ 傳送數量的百分比。這是行銷活動上唯一的一個「率」。
- **Number of Leads** — 這些成員中不重複的潛在客戶數。
- **Converted Leads** — 其中後來完成了轉化的潛在客戶數。
Expand Down
5 changes: 3 additions & 2 deletions src/marketing/actions/campaign.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ export const EnrollLeadsAction: Action = {
*
* The writer for the `responded` status, on the member row rather than on the
* campaign: a rep hears back from one person, and one membership changes.
* `num_responses` and `response_rate` are computed off that status, so an app
* with no writer for it reports a structural zero on every campaign.
* `num_responses` and `response_rate` count the `has_responded` flag that
* status stamps, so an app with no writer for it reports a structural zero on
* every campaign.
*
* A declarative update (`operation: 'update'`), written AS THE CALLER (#2167):
* the member's own `allowEdit` decides who may record a response, exactly as
Expand Down
Loading
Loading