```html 사이트 리드 통합 가이드 — Reactive CRM
Reactive CRM 사이트 리드 통합 가이드 ← 통합 가이드

웹사이트에서 리드 가져오기

웹사이트 양식을 ReactiveCRM과 통합하는 방법: 양식 제출을 리드로 캡처, 마케팅 속성 이벤트 전송, 결과 확인.

1. 개요

권장 흐름은 두 가지 요청으로 구성됩니다:

  1. 사이트가 양식 데이터를 자체 백엔드로 전송합니다.
  2. 사이트 백엔드가 POST /api/leads/create를 통해 CRM에 리드를 생성합니다.
  3. 생성 성공 후 백엔드가 POST /api/dashboard/marketing/events를 통해 lead_submitted 마케팅 이벤트를 전송하고, 받은 leadId를 전달합니다.
  4. CRM이 마케팅 속성을 위해 UTM 태그, 광고 식별자 및 리퍼러를 저장합니다.
텍스트
웹사이트 양식
    |
    v
사이트 백엔드 / 서버 측 프록시
    |  POST /api/leads/create
    v
ReactiveCRM -> leadId
    |  POST /api/dashboard/marketing/events
    v
마케팅 속성 및 대시보드

CRM JWT와 비밀을 브라우저에서 직접 전송하지 마세요. CRM 토큰과 서비스 식별자가 방문자에게 노출되지 않도록 사이트 백엔드 또는 서버리스 함수를 사용하세요.

2. 인증 및 기본 URL

모든 요청은 관련 테넌트의 컨텍스트에서 실행되며 CRM 인증이 필요합니다:

http
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json

예제에서는 다음을 사용합니다:

텍스트
CRM_BASE_URL=https://crm.example.com

자체 환경의 URL로 바꾸세요.

3. 사이트에서 수집할 데이터

리드 데이터

리드 생성을 위해 API는 다음을 지원합니다:

필드필수설명
message아니오양식의 문의 메시지 또는 텍스트
ownerId예리드를 담당하는 CRM 사용자의 UUID
authorId예리드를 생성한 CRM 사용자의 UUID
clientId아니오기존 클라이언트의 UUID
contactId아니오기존 연락처의 UUID
leadSourceId아니오리드 소스 트리의 노드 UUID
statusId아니오초기 상태의 UUID
quality아니오HOT, WARM, COOL 또는 COLD

ownerId와 authorId는 CRM 사용자의 UUID입니다. 공개 웹사이트 양식의 경우 방문자가 이러한 값을 직접 설정하도록 하지 마세요: 백엔드가 통합 구성에서 제공해야 합니다.

마케팅 방문 데이터

양식이 제출되기 전에 다음을 쿠키, 세션 스토리지 또는 백엔드에 저장하세요:

첫 방문 시 값을 저장하고 사이트 내에서 탐색할 때 빈 매개변수로 덮어쓰지 마세요.

4. 리드 생성

엔드포인트

http
POST /api/leads/create

요청 예제

bash
curl -X POST "$CRM_BASE_URL/api/leads/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "웹사이트 문의: 상담 요청",
    "ownerId": "11111111-1111-1111-1111-111111111111",
    "authorId": "11111111-1111-1111-1111-111111111111",
    "quality": "WARM"
  }'

201 Created 응답 예제

json
{
  "id": "22222222-2222-2222-2222-222222222222",
  "message": "웹사이트 문의: 상담 요청",
  "quality": "WARM",
  "dealId": null,
  "createdAt": "2026-09-05T20:00:00Z",
  "updatedAt": "2026-09-05T20:00:00Z",
  "version": 0,
  "author": {
    "id": "11111111-1111-1111-1111-111111111111",
    "firstName": "CRM",
    "lastName": "봇"
  },
  "owner": {
    "id": "11111111-1111-1111-1111-111111111111",
    "firstName": "CRM",
    "lastName": "봇"
  }
}

응답의 id를 저장하세요: 이 값은 마케팅 이벤트의 leadId 필드에 전달됩니다.

5. 리드 제출 이벤트 전송

엔드포인트

http
POST /api/dashboard/marketing/events

요청 예제

bash
curl -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "eventType": "lead_submitted",
    "occurredAt": "2026-09-05T20:00:00Z",
    "visitorId": "visitor-8b7f",
    "sessionId": "session-31ac",
    "leadId": "22222222-2222-2222-2222-222222222222",
    "externalId": "site-form-submit-20260905-000123",
    "source": "website",
    "channel": "paid",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "summer-consulting",
    "utmContent": "banner-a",
    "utmTerm": "crm consultation",
    "gclid": "EAIaIQobChMI-example",
    "landingUrl": "https://www.example.com/consultation",
    "referrer": "https://www.google.com/",
    "metadata": {
      "formName": "consultation",
      "pageType": "landing"
    }
  }'

응답 예제

json
{
  "accepted": true,
  "duplicate": false,
  "eventId": "33333333-3333-3333-3333-333333333333"
}

동일한 externalId가 이 source와 테넌트 쌍에 대해 이미 처리된 경우 API는 duplicate: true와 함께 성공 응답을 반환합니다. 이를 오류가 아닌 성공으로 처리하고 두 번째 리드를 생성하지 마세요.

6. 서버 측 핸들러 예제

다음은 간소화된 Node.js 예제입니다. 양식 데이터는 사이트 백엔드로 전송되어야 하며, 브라우저에서 CRM으로 직접 전송되지 않아야 합니다.

js
async function createWebsiteLead(form, attribution) {
  const headers = {
    Authorization: `Bearer ${process.env.CRM_ACCESS_TOKEN}`,
    'Content-Type': 'application/json',
  };

  const leadResponse = await fetch(
    `${process.env.CRM_BASE_URL}/api/leads/create`,
    {
      method: 'POST',
      headers,
      body: JSON.stringify({
        message: form.message || `웹사이트 문의: ${form.subject || '제목 없음'}`,
        ownerId: process.env.CRM_LEAD_OWNER_ID,
        authorId: process.env.CRM_LEAD_AUTHOR_ID,
        quality: 'WARM',
      }),
    },
  );

  if (!leadResponse.ok) {
    throw new Error(`CRM 리드 생성 실패: ${leadResponse.status}`);
  }

  const lead = await leadResponse.json();
  const externalId = `website-${form.requestId}`;

  const eventResponse = await fetch(
    `${process.env.CRM_BASE_URL}/api/dashboard/marketing/events`,
    {
      method: 'POST',
      headers,
      body: JSON.stringify({
        eventType: 'lead_submitted',
        occurredAt: new Date().toISOString(),
        visitorId: attribution.visitorId,
        sessionId: attribution.sessionId,
        leadId: lead.id,
        externalId,
        source: 'website',
        channel: attribution.channel || 'direct',
        utmSource: attribution.utmSource,
        utmMedium: attribution.utmMedium,
        utmCampaign: attribution.utmCampaign,
        utmContent: attribution.utmContent,
        utmTerm: attribution.utmTerm,
        gclid: attribution.gclid,
        fbclid: attribution.fbclid,
        landingUrl: attribution.landingUrl,
        referrer: attribution.referrer,
        metadata: { formName: form.formName || 'website' },
      }),
    },
  );

  if (!eventResponse.ok) {
    // 리드는 이미 생성되었습니다. 이벤트를 큐에 넣고
    // 두 번째 리드를 생성하는 대신 동일한 externalId로 재시도하세요.
    throw new Error(`CRM 마케팅 이벤트 실패: ${eventResponse.status}`);
  }

  return { leadId: lead.id, marketingEvent: await eventResponse.json() };
}

7. 멱등성 및 재시도

8. 개인 데이터 및 메타데이터

metadata에 개인 데이터 및 양식 내용을 전달하는 것은 금지됩니다:

개인 데이터는 해당 용도로 지정된 CRM 엔티티에서만 전달되어야 합니다 — 예를 들어, 사전 생성된 contactId/clientId에. metadata에는 기술적 속성만 유지하세요: 양식 이름, 페이지 유형, 배너 변형 등.

9. 일반적인 응답 및 오류

HTTP상황조치
201리드 생성됨id를 저장하고 lead_submitted 전송
200 + duplicate: false이벤트 수락됨eventId를 통합 로그에 저장
200 + duplicate: true이벤트가 이미 수락됨처리된 것으로 간주; 다시 전송하지 않음
400잘못된 데이터 또는 metadata의 PII페이로드 수정; 변경 없이 재시도는 무효
401토큰이 유효하지 않거나 누락됨백엔드에서 CRM 토큰 갱신
403토큰에 작업 권한이 없음역할 및 테넌트 확인
5xx / 시간 초과일시적인 CRM 또는 네트워크 오류동일한 externalId로 재시도; 리드에는 대기열 사용

10. CRM에서 결과 확인

통합 후 다음을 확인하세요:

  1. 리드가 GET /api/leads/{id} 또는 GET /api/leads/paged 목록에 나타납니다.
  2. 리드의 소유자, 작성자 및 생성 시간이 정확합니다.
  3. 마케팅 이벤트 응답의 첫 번째 전송 시 duplicate가 false입니다.
  4. 동일한 제출을 다시 전송하면 duplicate: true가 반환됩니다.
  5. 마케팅 대시보드에서 데이터가 올바른 기간, 채널 및 캠페인에 나타납니다.

생성된 리드 가져오기

bash
curl "$CRM_BASE_URL/api/leads/$LEAD_ID" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

목록 또는 조정을 위한 리드 가져오기

bash
curl "$CRM_BASE_URL/api/leads/paged?page=0&size=20&createdAtFrom=2026-09-05T00:00:00Z&createdAtTo=2026-09-05T23:59:59Z&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

page 매개변수는 0부터 시작하며 기본 size는 20입니다. 웹사이트 리드를 가져오려면 관련 데이터가 CRM에 이미 저장된 경우 message, createdAtFrom/createdAtTo, contactEmail 또는 search 필터를 추가로 사용하세요.

```