customer-retention
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseResources
资源
| File | When to use |
|---|---|
| Filter cookbook of churn signals — |
| 文件 | 使用场景 |
|---|---|
| 客户流失信号筛选手册 — 针对 |
Prereqs
前置要求
Read first — every read/write below uses its JSONL pipe, pagination, and dry-run/digest patterns. Activity-property tables and association rules live in .
bulk-operations/SKILL.mdsales-execution/SKILL.mdSchema is portal-specific. Verify each property before filtering — e.g. , , . If returns 403, your token lacks — use a private-app token with that scope.
hubspot properties get --type contacts notes_last_contacted... hs_last_sales_activity_date... --type subscriptions hs_subscription_statussubscriptionssubscriptions-read请先阅读 — 以下所有读写操作均使用其中的JSONL管道、分页以及试运行/摘要模式。活动属性表和关联规则可在中查看。
bulk-operations/SKILL.mdsales-execution/SKILL.md数据结构因门户而异。筛选前请验证每个属性 — 例如、、。如果返回403错误,说明你的令牌缺少权限 — 请使用具备该权限的私有应用令牌。
hubspot properties get --type contacts notes_last_contacted... hs_last_sales_activity_date... --type subscriptions hs_subscription_statussubscriptionssubscriptions-read1 — Find inactive customers
1 — 查找不活跃客户
bash
CUTOFF=$(date -v-60d +%Y-%m-%d 2>/dev/null || date -d '60 days ago' +%Y-%m-%d)bash
CUTOFF=$(date -v-60d +%Y-%m-%d 2>/dev/null || date -d '60 days ago' +%Y-%m-%d)No outreach in 60d (calls/notes/meetings update notes_last_contacted)
60天内无 outreach(电话/备注/会议会更新notes_last_contacted)
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties email,firstname,notes_last_contacted,hubspot_owner_id
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties email,firstname,notes_last_contacted,hubspot_owner_id
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties email,firstname,notes_last_contacted,hubspot_owner_id
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties email,firstname,notes_last_contacted,hubspot_owner_id
No sales activity in 60d (broader — also catches emails/tasks)
60天内无销售活动(范围更广 — 还包含邮件/任务)
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND hs_last_sales_activity_date<$CUTOFF"
--properties email,firstname,hs_last_sales_activity_date
--filter "lifecyclestage=customer AND hs_last_sales_activity_date<$CUTOFF"
--properties email,firstname,hs_last_sales_activity_date
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND hs_last_sales_activity_date<$CUTOFF"
--properties email,firstname,hs_last_sales_activity_date
--filter "lifecyclestage=customer AND hs_last_sales_activity_date<$CUTOFF"
--properties email,firstname,hs_last_sales_activity_date
Never contacted
从未联系过
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND !notes_last_contacted"
--properties email,firstname
--filter "lifecyclestage=customer AND !notes_last_contacted"
--properties email,firstname
For more signals (email opt-out, stale tickets, no open deals) see `resources/customer-health-signals.md`. For >100 hits, use the pagination loop from `bulk-operations`.hubspot objects search --type contacts
--filter "lifecyclestage=customer AND !notes_last_contacted"
--properties email,firstname
--filter "lifecyclestage=customer AND !notes_last_contacted"
--properties email,firstname
更多信号(邮件退订、停滞工单、无未结交易)请查看`resources/customer-health-signals.md`。如果搜索结果超过100条,请使用`bulk-operations`中的分页循环。2 — Flag at-risk subscriptions
2 — 标记高风险订阅
subscriptionshubspot objects typeshs_subscription_statusbash
hubspot properties get --type subscriptions hs_subscription_status # lists allowed valuessubscriptionshubspot objects typeshs_subscription_statusbash
hubspot properties get --type subscriptions hs_subscription_status # 列出允许的值Past-due — revenue at immediate risk (substitute your verified value)
逾期 — 收入面临直接风险(替换为你验证后的值)
hubspot objects search --type subscriptions
--filter "hs_subscription_status=past_due"
--properties hs_recurring_billing_total,hs_subscription_status
--filter "hs_subscription_status=past_due"
--properties hs_recurring_billing_total,hs_subscription_status
hubspot objects search --type subscriptions
--filter "hs_subscription_status=past_due"
--properties hs_recurring_billing_total,hs_subscription_status
--filter "hs_subscription_status=past_due"
--properties hs_recurring_billing_total,hs_subscription_status
Map an at-risk subscription to its contact for outreach
将高风险订阅关联到对应联系人以进行触达
hubspot associations list --from subscriptions:<sub_id> --to contacts --format jsonl
undefinedhubspot associations list --from subscriptions:<sub_id> --to contacts --format jsonl
undefined3 — Create a follow-up task or check-in note
3 — 创建跟进任务或回访备注
Activity creation lives in (full property tables, note + meeting flows). One anchor example — unassociated tasks are invisible in the CRM UI, so always associate:
sales-executionbash
task_id=$(hubspot objects create --type tasks \
--property hs_task_subject="Q1 retention check-in" \
--property hs_task_priority=HIGH --property hs_task_status=NOT_STARTED \
--property hs_task_type=CALL --property hs_timestamp=$(date +%s)000 \
--format json | jq -r '.id')
hubspot associations create --from tasks:$task_id --to contacts:<contact_id>活动创建的相关内容在中(包含完整属性表、备注+会议流程)。一个核心示例 — 未关联的任务在CRM界面中不可见,因此务必进行关联:
sales-executionbash
task_id=$(hubspot objects create --type tasks \
--property hs_task_subject="Q1 retention check-in" \
--property hs_task_priority=HIGH --property hs_task_status=NOT_STARTED \
--property hs_task_type=CALL --property hs_timestamp=$(date +%s)000 \
--format json | jq -r '.id')
hubspot associations create --from tasks:$task_id --to contacts:<contact_id>4 — Bulk task creation for a cohort
4 — 为客户群体批量创建任务
Pipe a search through into one call, then associate. Preview with first ( covers digest/confirm for >100 rows).
jqobjects create--dry-runbulk-operationsbash
DUE_MS=$(( ($(date +%s) + 2*86400) * 1000 )) # due in 2 days将搜索结果通过管道传递到一个调用中,然后进行关联。请先使用预览(涵盖了超过100行数据的摘要/确认功能)。
jqobjects create--dry-runbulk-operationsbash
DUE_MS=$(( ($(date +%s) + 2*86400) * 1000 )) # 2天后到期1. Capture the cohort (same file feeds both create + associate)
1. 捕获客户群体(同一文件用于创建任务和关联操作)
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties firstname > /tmp/inactive.jsonl
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties firstname > /tmp/inactive.jsonl
hubspot objects search --type contacts
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties firstname > /tmp/inactive.jsonl
--filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF"
--properties firstname > /tmp/inactive.jsonl
2. Build task payloads — one per contact
2. 构建任务负载 — 每个联系人对应一个任务
jq -c --arg due "$DUE_MS" '{
contact_id: .id,
properties: {
hs_task_subject: ("Re-engage: " + (.properties.firstname // "customer")),
hs_task_priority: "HIGH", hs_task_status: "NOT_STARTED",
hs_task_type: "CALL", hs_timestamp: $due
}
}' /tmp/inactive.jsonl > /tmp/task_payloads.jsonl
jq -c --arg due "$DUE_MS" '{
contact_id: .id,
properties: {
hs_task_subject: ("Re-engage: " + (.properties.firstname // "customer")),
hs_task_priority: "HIGH", hs_task_status: "NOT_STARTED",
hs_task_type: "CALL", hs_timestamp: $due
}
}' /tmp/inactive.jsonl > /tmp/task_payloads.jsonl
3. Dry-run, then create (drop contact_id before piping)
3. 试运行,然后创建任务(传递前移除contact_id)
jq -c '{properties}' /tmp/task_payloads.jsonl | hubspot objects create --type tasks --dry-run | head
jq -c '{properties}' /tmp/task_payloads.jsonl | hubspot objects create --type tasks > /tmp/created.jsonl
jq -c '{properties}' /tmp/task_payloads.jsonl | hubspot objects create --type tasks --dry-run | head
jq -c '{properties}' /tmp/task_payloads.jsonl | hubspot objects create --type tasks > /tmp/created.jsonl
4. Associate each new task to its contact (paste preserves order)
4. 将每个新任务关联到对应联系人(paste命令可保持顺序一致)
paste <(jq -r '.id' /tmp/created.jsonl) <(jq -r '.contact_id' /tmp/task_payloads.jsonl)
| while read task_id contact_id; do hubspot associations create --from tasks:$task_id --to contacts:$contact_id done
| while read task_id contact_id; do hubspot associations create --from tasks:$task_id --to contacts:$contact_id done
One CLI call for the search, one for the create, then N for associations — no `xargs -I{}` per record. The output-order guarantee of `objects create` (one result per stdin line, in order — see `bulk-operations` "Output shape") is what makes the `paste` correct.paste <(jq -r '.id' /tmp/created.jsonl) <(jq -r '.contact_id' /tmp/task_payloads.jsonl)
| while read task_id contact_id; do hubspot associations create --from tasks:$task_id --to contacts:$contact_id done
| while read task_id contact_id; do hubspot associations create --from tasks:$task_id --to contacts:$contact_id done
一次CLI调用完成搜索,一次调用完成任务创建,然后N次调用完成关联 — 无需为每条记录使用`xargs -I{}`。`objects create`的输出顺序保证(每行标准输入对应一个结果,顺序一致 — 详见`bulk-operations`中的“输出格式”)是`paste`命令能够正确执行的关键。Known gaps
已知不足
- No native churn-score / health-score property — track via a custom property.
- No Lists API, no sequences/cadences API — re-engagement enrollment is not CLI-available.
- does not batch — one CLI call per pair.
hubspot associations create
- 无原生客户流失评分/健康评分属性 — 需通过自定义属性进行追踪。
- 无列表API、无序列/节奏API — 无法通过CLI完成重新触达的登记操作。
- 不支持批量操作 — 每对关联需单独调用一次CLI。
hubspot associations create