Reactive CRM 다중 계약 웹사이트 리드 수집 ← 통합 가이드

다중 계약 웹사이트 리드 수집

이 문서는 사이트 백엔드가 리드 데이터, 방문자의 연락처 세부 정보 및 마케팅 UTM 메트릭을 하나의 요청으로 ReactiveCRM에 전송하는 단일 API 계약을 설명합니다.

1. 목적

사이트 통합자는 연락처, 전화번호, 이메일, 리드 및 마케팅 이벤트를 별도로 생성할 필요가 없습니다. 하나의 요청이 원자적으로 다음을 생성해야 합니다:

  1. 연락처;
  2. 연락처의 기본 전화번호;
  3. 제공된 경우 연락처의 기본 이메일;
  4. 리드;
  5. 연락처와 리드 간의 연결;
  6. 마케팅 이벤트 및 UTM 속성.

어느 단계라도 실패하면 전체 요청이 롤백되고 부분적으로 생성된 데이터는 저장되지 않습니다.

2. 엔드포인트

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

토큰은 사이트 백엔드 또는 서버리스 함수에서만 전달되어야 합니다. 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에는 다음 리드가 포함됩니다:

이 세트는 관리자가 제출을 확인하고, 연락처에 전화하고, 리드를 평가하기에 충분합니다.