自动化与脚本
在 HubSpot CLI 中端到端管理 deal…
适用于需要通过 HubSpot CLI 在运行时发现阶段并批量处理 deal 全生命周期的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 HubSpot CLI 中端到端管理特定
解决思路
- 先阅读 `bulk-operations/SKILL.md`,掌握 JSONL piping、batch read、pagination、dry-run/digest/confirm 流程;reshape recipes 查看 `bulk-operations/resources/json-patterns.md`;用 `hubspot <command> --help` 查命令;对象类型用复数(`contacts`、`deals`、`companies`);查属性用 `hubspot properties list --type deals`,不要硬编码属性表。
- 运行时发现 pipelines 和 stages:运行 `hubspot pipelines list --type deals --format jsonl` 获取 pipeline 的 id/label/displayOrder;pipeline 和 stage ID 是 portal-specific,绝不要跨 portal 硬编码。
- 运行 `hubspot pipelines stages --type deals --pipeline default --format jsonl` 获取 stage 的 id/label/displayOrder;用 `QUALIFIED=$(hubspot pipelines stages --type deals --pipeline default --format jsonl | jq -r 'select(.label=="Qualified To Buy") | .id')` 按 label 取特定 stage ID;每次运行都重新发现你自己的 stages,因为 portal 可能重命名或移除标准 `default` pipeline stages。
- 查找已连接且无 deal 的 MQL:运行 `hubspot objects search --type contacts --filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0" --properties email,firstname,lastname,company,hubspot_owner_id`。
- 单个 MQL 转 deal 时,先通过 `hubspot associations list --from contacts:<contact_id> --to companies` 找 company,得到 `<company_id>`。
- 为单个 contact 创建 deal:运行 `hubspot objects create --type deals --property "dealname=Acme Corp - Inbound" --property pipeline=default --property dealstage=qualifiedtobuy --property amount=0 --property hubspot_owner_id=<owner_id>`,从返回中获取 `<deal_id>`。
- 创建 deal 后,用 `hubspot associations create --from deals:<deal_id> --to contacts:<contact_id>` 和 `hubspot associations create --from deals:<deal_id> --to companies:<company_id>` 分别关联 contact 和 company。
- 提升单个 contact 生命周期:运行 `hubspot objects update --type contacts <contact_id> --property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL`。
- 批量 MQL 转 deal 时,先快照 MQL 到文件以保留顺序:`hubspot objects search --type contacts --filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0" --properties email,firstname,lastname,company,hubspot_owner_id > /tmp/mqls.jsonl`。
- 批量创建 deal:用 `jq -c '{properties:{dealname: ((.properties.firstname // "") + " " + (.properties.lastname // "") + " - " + (.properties.company // "Unknown")), pipeline:"default", dealstage:"qualifiedtobuy", amount:"0", dealtype:"newbusiness", hubspot_owner_id:(.properties.hubspot_owner_id // "")}}' /tmp/mqls.jsonl | hubspot objects create --type deals > /tmp/deals.jsonl`,`objects create` 每行 stdin 返回一行结果并保持输入顺序。
- 批量创建后,若任何 create 失败则中止:`jq -e 'select(.ok==false)' /tmp/deals.jsonl > /dev/null && { echo "Some deal creates failed — inspect /tmp/deals.jsonl" >&2; exit 1; }`,否则会把 null deal IDs 与真实 contacts 配对。
- 批量关联 contact 和新 deal:用 `paste <(jq -r '.id' /tmp/mqls.jsonl) <(jq -r '.id' /tmp/deals.jsonl) | jq -cR 'split("\t") | {from:("deals:" + .[1]), to:("contacts:" + .[0])}' | hubspot associations create` 按行配对。
- 批量提升 contact 生命周期:`jq -c '{id, properties:{lifecyclestage:"salesqualifiedlead", hs_lead_status:"OPEN_DEAL"}}' /tmp/mqls.jsonl | hubspot objects update --type contacts`。
- 公司关联需要单独的逐 contact 流程:对每个 contact 运行 `hubspot associations list --from contacts:<id> --to companies`,因为一个 contact 可能有零个或多个 company。
- 预资格审查直接用 search filter 表达:有 email、有 company、无 open deal、有 owner,都已放在 `--filter` 中;完整阶段推进和 contact 侧更新见 `resources/lifecycle-stage-progression.md`。
- 批量推进 deal 前先预览:运行 `hubspot objects search --type deals --filter "dealstage=qualifiedtobuy" | jq -c '{id, properties:{dealstage:"presentationscheduled"}}' | hubspot objects update --type deals --dry-run`,确认后去掉 `--dry-run` 再运行。
- 批量重新分配 open deals:先从 `hubspot owners list --format jsonl` 取 owner ID,例如 `OLD=$(hubspot owners list --format jsonl | jq -r 'select(.email=="old@co.com") | .id')`、`NEW=$(hubspot owners list --format jsonl | jq -r 'select(.email=="new@co.com") | .id')`;再运行 `hubspot objects search --type deals --filter "hubspot_owner_id=$OLD AND hs_is_closed!=true" | jq -c "{id, properties:{hubspot_owner_id:\"$NEW\"}}" | hubspot objects update --type deals --dry-run`,确认后去掉 `--dry-run` 再运行。
- 超过 100 行时,dry-run 会输出 digest 行;重新 pipe 时用 `--digest <hash> --confirm <count>`;完整流程见 `bulk-operations/SKILL.md`。
- 查找 stalled deals:运行核心查询 `hubspot objects search --type deals --filter "hs_last_activity_date<$(date -v-30d +%Y-%m-%d) AND hs_is_closed!=true" --properties dealname,dealstage,closedate,hubspot_owner_id,hs_last_activity_date`;动态日期 filter cookbook 在 `resources/stalled-deal-queries.md`。
- 将 stalled deals 查询结果 pipe 到 update(例如延长 close dates、移动 stage、设置 flag)或 task creation;后续 tasks/calls/notes 见 `sales-execution`,不要在这里重复 activity-object property handling。
- 延长所有逾期 close dates:运行 `hubspot objects search --type deals --filter "closedate<$(date +%Y-%m-%d) AND hs_is_closed!=true" | jq -c '{id, properties:{closedate:"2026-06-30"}}' | hubspot objects update --type deals --dry-run`,确认后去掉 `--dry-run` 再运行。
- 关闭单个 deal:运行 `hubspot objects update --type deals <deal_id> --property dealstage=closedwon --property closedate=2026-05-15`;关闭就是 stage 更新 + `closedate`(`YYYY-MM-DD`),`hs_is_closed` 和 `hs_is_closed_won` 是只读的,由 stage 派生。
- 批量关闭 deal 前先预览:运行 `hubspot objects search --type deals --filter "dealstage=contractsent AND hubspot_owner_id=<owner_id>" | jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}' | hubspot objects update --type deals --dry-run`,确认后去掉 `--dry-run` 再运行;赢/输分析见 `sales-reporting`。
- 批量 MQL → deal 需要两遍 shell flow:associations 必须从 `objects create` 输出构建,不能放在同一个 pipe 中。
- 注意 `lifecyclestage` 在多数 portal 设置中是 forward-only,向后转换可能被拒绝。
- `closedate` 是日期字符串(`YYYY-MM-DD`);datetime activity props(如 `hs_last_activity_date`)也接受日期字符串用于 `<`/`>` 比较。
- CLI 没有 sequences/cadences API;需要后续任务时用 `sales-execution` 创建 follow-up task。
适用边界 · 注意事项
- 没有安装/认证 HubSpot CLI,或没有对应 HubSpot 账号/权限时,不能执行这些命令。
- 需要 sequences/cadences API 或 activity-object 的完整处理时,不应在本技能中做;CLI 不支持 sequences/cadences,后续任务/通话/笔记应交给 `sales-execution`。
- 不要在未运行时发现 pipeline/stage ID 的情况下跨 portal 硬编码 `pipeline` 或 `dealstage`,也不要期望向后转换 `lifecyclestage` 一定成功。