Reactive CRM 多渠道网站线索接收 ← 集成指南

多渠道网站线索接收

本文档描述了一个单一的 API 契约,网站后端通过该契约在一个请求中将线索数据、访客联系详情和营销 UTM 指标发送到 ReactiveCRM。

1. 目的

网站集成者无需分别创建联系人、电话、邮箱、线索和营销事件。一个请求必须原子性地创建:

  1. 联系人;
  2. 联系人的主要电话;
  3. 联系人的主要邮箱(如果提供);
  4. 线索;
  5. 联系人与线索之间的关联;
  6. 营销事件和 UTM 归因。

如果任何步骤失败,整个请求将被回滚,部分创建的数据不会保存。

2. 端点

http
POST /api/site/leads
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json

令牌必须仅从网站后端或 Serverless 函数传递。绝不要将 CRM 令牌放在浏览器 JavaScript 中。

租户由授权令牌确定。所有提供的 UUID 都在此租户内进行验证。

3. 完整 JSON 契约

json
{
  "externalId": "site-form-01J7K9A2M4Y5T6",
  "lead": {
    "leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47",
    "quality": "WARM",
    "message": "我想咨询 CRM 实施"
  },
  "contact": {
    "firstName": "伊万",
    "lastName": "伊万诺夫",
    "phone": "+79991234567",
    "email": "ivan@example.com"
  },
  "marketing": {
    "occurredAt": "2026-09-06T18:00:00Z",
    "visitorId": "visitor-8b7f",
    "sessionId": "session-31ac",
    "source": "website",
    "channel": "paid",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "summer-consulting",
    "utmContent": "banner-a",
    "utmTerm": "crm consultation",
    "gclid": "EAIaIQobChMI-example",
    "fbclid": null,
    "landingUrl": "https://example.com/consultation",
    "referrer": "https://www.google.com/"
  }
}

4. 请求字段

4.1. 根字段

字段类型必填描述
externalId字符串推荐用于幂等性的表单提交稳定唯一 ID
lead对象是正在创建的线索数据
contact对象是联系人数据
marketing对象否营销访问的 UTM 指标和技术数据

externalId 在首次发送尝试之前生成。在超时或网络错误后重复请求时,请使用相同的值。

4.2. lead 对象

字段类型必填描述
leadSourceIduuid是当前租户中的线索来源 ID
quality字符串否初始评级:HOT、WARM、COOL 或 COLD
message字符串否访客消息或提交评论

如果网站不执行预评估,最好不发送 quality 字段。

4.3. contact 对象

字段类型必填描述
firstName字符串是联系人的名
lastName字符串否联系人的姓
phone字符串是主要电话;推荐 E.164 格式
email字符串(邮箱)否联系人的主要邮箱

处理提交所需的最小数据是 firstName 和 phone。

4.4. marketing 对象

字段类型必填描述
occurredAt日期-时间否表单提交时间;未提供时使用 CRM 时间
visitorId字符串否匿名访客 ID
sessionId字符串否网站会话 ID
source字符串否事件来源,默认为 website
channel字符串否渠道:例如 paid、organic、social、email、direct
utmSource字符串否utm_source 值
utmMedium字符串否utm_medium 值
utmCampaign字符串否utm_campaign 值
utmContent字符串否utm_content 值
utmTerm字符串否utm_term 值
gclid字符串否Google 点击 ID
fbclid字符串否Meta/Facebook 点击 ID
landingUrl字符串否着陆页 URL
referrer字符串否上一页 URL

个人数据不得在营销对象中重复。姓名、电话、邮箱和消息文本仅在 contact 和 lead 中传递。

5. 最小请求

json
{
  "externalId": "site-form-550e8400-e29b-41d4-a716-446655440000",
  "lead": {
    "leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47"
  },
  "contact": {
    "firstName": "伊万",
    "phone": "+79991234567"
  }
}

6. 成功响应

首次请求 — 201 Created

json
{
  "leadId": "22222222-2222-2222-2222-222222222222",
  "contactId": "33333333-3333-3333-3333-333333333333",
  "phoneId": "44444444-4444-4444-4444-444444444444",
  "emailId": "55555555-5555-5555-5555-555555555555",
  "marketingEventId": "66666666-6666-6666-6666-666666666666",
  "duplicate": false,
  "createdAt": "2026-09-06T18:00:01Z"
}

如果未提供邮箱或营销数据,相应的 ID 将以 null 返回。

使用相同 externalId 重复 — 200 OK

json
{
  "leadId": "22222222-2222-2222-2222-222222222222",
  "contactId": "33333333-3333-3333-3333-333333333333",
  "phoneId": "44444444-4444-4444-4444-444444444444",
  "emailId": "55555555-5555-5555-5555-555555555555",
  "marketingEventId": "66666666-6666-6666-6666-666666666666",
  "duplicate": true,
  "createdAt": "2026-09-06T18:00:01Z"
}

重复请求不得创建第二个线索或联系人。

7. cURL 示例

bash
curl -X POST "$CRM_BASE_URL/api/site/leads" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "site-form-01J7K9A2M4Y5T6",
    "lead": {
      "leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47",
      "quality": "WARM",
      "message": "回电给我"
    },
    "contact": {
      "firstName": "伊万",
      "lastName": "伊万诺夫",
      "phone": "+79991234567",
      "email": "ivan@example.com"
    },
    "marketing": {
      "utmSource": "google",
      "utmMedium": "cpc",
      "utmCampaign": "crm-demo",
      "landingUrl": "https://example.com/demo"
    }
  }'

8. TypeScript 接口

ts
type LeadQuality = 'HOT' | 'WARM' | 'COOL' | 'COLD';

interface SiteLeadRequest {
  externalId?: string;
  lead: {
    leadSourceId: string;
    quality?: LeadQuality;
    message?: string;
  };
  contact: {
    firstName: string;
    lastName?: string;
    phone: string;
    email?: string;
  };
  marketing?: {
    occurredAt?: string;
    visitorId?: string;
    sessionId?: string;
    source?: string;
    channel?: string;
    utmSource?: string;
    utmMedium?: string;
    utmCampaign?: string;
    utmContent?: string;
    utmTerm?: string;
    gclid?: string;
    fbclid?: string;
    landingUrl?: string;
    referrer?: string;
  };
}

interface SiteLeadResponse {
  leadId: string;
  contactId: string;
  phoneId: string;
  emailId: string | null;
  marketingEventId: string | null;
  duplicate: boolean;
  createdAt: string;
}

9. 服务端示例

ts
export async function sendLeadToCrm(payload: SiteLeadRequest): Promise<SiteLeadResponse> {
  const response = await fetch(`${process.env.CRM_BASE_URL}/api/site/leads`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.CRM_ACCESS_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    const body = await response.text();
    throw new Error(`ReactiveCRM returned ${response.status}: ${body}`);
  }

  return response.json() as Promise<SiteLeadResponse>;
}

10. 错误

HTTP原因集成者操作
400格式错误、缺少必填字段、邮箱/电话/quality 无效修复数据;不要在不修改的情况下自动重试
401令牌缺失或无效刷新集成令牌
403无权访问租户或操作检查集成用户和角色
404在当前租户中未找到 leadSourceId在网站设置中更新来源 ID
409externalId 已链接到不兼容的请求检查 ID 生成和集成日志
5xx临时 CRM 错误使用相同的 externalId 重试相同请求

验证错误示例:

json
{
  "status": 400,
  "error": "Bad Request",
  "message": "contact.phone must not be blank",
  "path": "/api/site/leads"
}

11. 幂等性

12. 网站开发者迷你指南

  1. 首次访问时,存储 UTM 标签、gclid、fbclid、着陆 URL 和引用来源。
  2. 提交表单时,生成稳定的 externalId。
  3. 将表单发送到网站后端。
  4. 后端添加 CRM 令牌并调用 POST /api/site/leads。
  5. 在 201 或 200 且 duplicate: true 时,视为提交已送达。
  6. 超时或 5xx 时,使用相同的 externalId 重试请求。
  7. 绝不要从浏览器直接发送 CRM 令牌。

13. CRM 管理者获得的内容

成功请求后,CRM 包含一个线索,该线索:

这些信息足以让管理者查看提交、联系联系人并评估线索。