mcpField
C
crm-data-quality

crm-data-quality

github.com/hubspot数据与数据库281.8k 次安装今天更新
代码仓库

关于 crm-data-quality

crm-data-quality 是一项通过 hubspot 命令行工具维护 HubSpot CRM 数据的技能,涵盖属性检查、查找信息不完整的记录、规范字段值、去重和属性审计,并为破坏性操作设置安全步骤。

主要功能

  1. 01发现 CRM 属性名称和枚举选项
  2. 02查找缺少字段的记录
  3. 03用 jq 管道规范字段值
  4. 04通过安全步骤合并重复记录
  5. 05审计和管理属性

适用场景

  1. 01查找缺少邮箱或电话的联系人
  2. 02统一公司字段的值
  3. 03查找并合并重复联系人
  4. 04检查枚举选项和属性分组

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hubspot/agent-cli-skills --skill crm-data-quality

安装后在 Claude Code 中输入/crm-data-quality确认已加载。

详细介绍

先阅读 bulk-operations/SKILL.md——JSONL 管道传输、批量读取、分页以及 dry-run/digest/confirm 门控适用于以下所有命令。

属性发现

不要猜测属性名称。先列出:

hubspot properties list --type contacts --format table
hubspot properties list --type contacts | jq -c 'select(.type=="enumeration") | {name, label}'

--type companies、deals 或任何自定义类型(hubspot objects types)也同样适用。

1. 查找不完整记录

!name = NOT_HAS_PROPERTY(缺失或为空)。单独的 name = HAS_PROPERTY。在一个 --filter 中使用 AND 链接条件;多个 --filter 标志之间使用 OR。

hubspot objects search --type contacts --filter "!email" --properties firstname,lastname,company
hubspot objects search --type contacts --filter "!phone AND !mobilephone" --properties email
hubspot objects search --type contacts --filter "!hubspot_owner_id" --properties email,lifecyclestage

结果超过 100 条时,使用 bulk-operations 中的分页循环。

2. 规范化字段值

搜索 → 使用 jq 重塑 → 管道传入 update。objects update 不可逆,因此要先运行 --dry-run——无论行数多少,都必须遵循 dry-run → digest → confirm 流程,不仅限于超过 100 行的情况(bulk-operations 中有完整说明)。重塑模式见:bulk-operations/resources/json-patterns.md。

# Collapse spellings into one canonical value — 1. preview
hubspot objects search --type contacts --filter "company~acme" \
| jq -c '{id, properties:{company:"Acme Corporation"}}' \
| hubspot objects update --type contacts --dry-run \
| tee /tmp/normalize.preview.jsonl

# 2. lift the digest + confirm (present at every row count)
digest=$(jq -r 'select(.digest != null) | .digest' /tmp/normalize.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/normalize.preview.jsonl)   # single: record ID; batch of 2+: row count

# 3. execute — re-pipe the SAME inputs plus --digest/--confirm
hubspot objects search --type contacts --filter "company~acme" \
| jq -c '{id, properties:{company:"Acme Corporation"}}' \
| hubspot objects update --type contacts --digest "$digest" --confirm "$confirm"

# Lowercase emails (read, reshape, write) — 1. preview
hubspot objects search --type contacts --filter "email" --properties email \
| jq -c '{id, properties:{email: (.properties.email | ascii_downcase)}}' \
| hubspot objects update --type contacts --dry-run \
| tee /tmp/lower.preview.jsonl

# 2. lift the digest + confirm, then 3. re-pipe the SAME inputs to execute
digest=$(jq -r 'select(.digest != null) | .digest' /tmp/lower.preview.jsonl)
confirm=$(jq -r 'select(.digest != null) | .target.id' /tmp/lower.preview.jsonl)
hubspot objects search --type contacts --filter "email" --properties email \
| jq -c '{id, properties:{email: (.properties.email | ascii_downcase)}}' \
| hubspot objects update --type contacts --digest "$digest" --confirm "$confirm"

3. 使用 hubspot objects merge 去重

次要记录会合并到主要记录中并被删除。**不可逆。**适用 dry-run/digest/confirm 门控。

# Single pair — dry-run first, then execute with the digest + confirm (confirm = the secondary ID for one pair)
hubspot objects merge --type contacts --primary 149 --secondary 425 --dry-run
hubspot objects merge --type contacts --primary 149 --secondary 425 --digest <hash> --confirm 425

批量操作:通过 stdin 传入 JSONL {"primary":"...","secondary":"..."}(省略 --primary/--secondary)。

必须分页。objects search 每次调用最多返回 100 行,而 jq -s 会将单个数据流全部读入内存——对原始 search 运行下面的代码片段时,任何跨越分页边界的重复项都会被悄然遗漏。先使用 bulk-operations/SKILL.md 中的分页循环收集完整数据集(写入 /tmp/contacts.jsonl),然后再从文件中去重:

# /tmp/contacts.jsonl produced by the pagination loop (bulk-operations/SKILL.md)
jq -s -c '
    group_by(.properties.email)[]
    | select(length > 1)
    | sort_by(.id | tonumber)
    | .[0].id as $p | .[1:][] | {primary: $p, secondary: .id}
  ' /tmp/contacts.jsonl \
| hubspot objects merge --type contacts --dry-run | tee /tmp/merge-preview.jsonl

无论数据量大小,都从预览行中提取 digest/confirm——使用 select(.digest != null);对于批次,confirm 是配对数量(.target.id),而 mutation_kind 仅在超过 100 行的阈值时为 BulkData(100 行或以下为 RecordMutation,但无论哪种情况都会提供 digest)。使用 --digest/--confirm 重新传入同一生产端(参见 bulk-operations)。

4. 审计属性

hubspot properties list(以及 get、batch-read)会为每一行输出 {name, label, type, fieldType, groupName, optionsDisplay}。枚举选项值可通过 properties options-list 获取——无需从实时记录或 UI 中读取。

# Count properties per group (HubSpot groups standard fields; custom groups stand out)
hubspot properties list --type contacts | jq -rs 'group_by(.groupName) | map({group: .[0].groupName, count: length}) | .[]'

# All enumeration properties
hubspot properties list --type contacts | jq -c 'select(.type=="enumeration") | {name, label, fieldType}'

# Create a DQ flag property, then set it via the normalize pattern in section 2
hubspot properties create --type contacts --name dq_missing_phone --label "DQ: Missing Phone" --prop-type string --field-type text
枚举选项——列出和管理(properties options-*,v0.11.0)
# List the allowed options on an enumeration property
hubspot properties options-list --type contacts hs_buying_role
# each row: {"value":"EVALUATOR","label":"Evaluator","displayOrder":9,"hidden":false}

# Add / rename / remove an option (options-delete is irreversible — dry-run → digest → confirm, confirm = the option value)
hubspot properties options-create --type contacts hs_buying_role --label "Evaluator" --value EVALUATOR --display-order 9
hubspot properties options-update --type contacts hs_buying_role --value EVALUATOR --label "New Label"
hubspot properties options-delete --type contacts hs_buying_role --value EVALUATOR --dry-run
hubspot properties options-delete --type contacts hs_buying_role --value EVALUATOR --digest <hash> --confirm EVALUATOR

对于选项只读的 HubSpot 定义属性,options-create/update/delete 会在调用 API 前被拒绝。

恢复

合并不可逆。每次合并后,hubspot history --since 1h 会记录审计跟踪。如果方向错误,请从 UI 的回收站恢复次要记录。

评论

支持 Markdown