웹사이트에서 리드 가져오기
웹사이트 양식을 ReactiveCRM과 통합하는 방법: 양식 제출을 리드로 캡처, 마케팅 속성 이벤트 전송, 결과 확인.
1. 개요
권장 흐름은 두 가지 요청으로 구성됩니다:
- 사이트가 양식 데이터를 자체 백엔드로 전송합니다.
- 사이트 백엔드가
POST /api/leads/create를 통해 CRM에 리드를 생성합니다. - 생성 성공 후 백엔드가
POST /api/dashboard/marketing/events를 통해lead_submitted마케팅 이벤트를 전송하고, 받은leadId를 전달합니다. - CRM이 마케팅 속성을 위해 UTM 태그, 광고 식별자 및 리퍼러를 저장합니다.
웹사이트 양식
|
v
사이트 백엔드 / 서버 측 프록시
| POST /api/leads/create
v
ReactiveCRM -> leadId
| POST /api/dashboard/marketing/events
v
마케팅 속성 및 대시보드
CRM JWT와 비밀을 브라우저에서 직접 전송하지 마세요. CRM 토큰과 서비스 식별자가 방문자에게 노출되지 않도록 사이트 백엔드 또는 서버리스 함수를 사용하세요.
2. 인증 및 기본 URL
모든 요청은 관련 테넌트의 컨텍스트에서 실행되며 CRM 인증이 필요합니다:
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입니다. 공개 웹사이트 양식의 경우 방문자가 이러한 값을 직접 설정하도록 하지 마세요: 백엔드가 통합 구성에서 제공해야 합니다.
마케팅 방문 데이터
양식이 제출되기 전에 다음을 쿠키, 세션 스토리지 또는 백엔드에 저장하세요:
utm_source→utmSourceutm_medium→utmMediumutm_campaign→utmCampaignutm_content→utmContentutm_term→utmTermgclid— Google Ads 식별자fbclid— Meta/Facebook 식별자- 랜딩 페이지 URL →
landingUrl - 이전 페이지 URL →
referrer - 자체 방문자 및 세션 식별자 →
visitorId,sessionId
첫 방문 시 값을 저장하고 사이트 내에서 탐색할 때 빈 매개변수로 덮어쓰지 마세요.
4. 리드 생성
엔드포인트
POST /api/leads/create
요청 예제
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 응답 예제
{
"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. 리드 제출 이벤트 전송
엔드포인트
POST /api/dashboard/marketing/events
요청 예제
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"
}
}'
응답 예제
{
"accepted": true,
"duplicate": false,
"eventId": "33333333-3333-3333-3333-333333333333"
}
동일한 externalId가 이 source와 테넌트 쌍에 대해 이미 처리된 경우 API는 duplicate: true와 함께 성공 응답을 반환합니다. 이를 오류가 아닌 성공으로 처리하고 두 번째 리드를 생성하지 마세요.
6. 서버 측 핸들러 예제
다음은 간소화된 Node.js 예제입니다. 양식 데이터는 사이트 백엔드로 전송되어야 하며, 브라우저에서 CRM으로 직접 전송되지 않아야 합니다.
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. 멱등성 및 재시도
- 각 양식 제출에 대해 안정적인
externalId를 생성하세요. 예를 들어, 첫 번째 요청 전에 생성된 UUID 또는 고유한 양식requestId를 사용하세요. - 네트워크 오류 시 동일한
externalId로 마케팅 이벤트 요청을 재시도하세요. - 재시도 시 새
externalId를 생성하지 마세요: 중복 이벤트가 생성됩니다. - 리드 생성 요청이 시간 초과로 인해 알 수 없는 결과로 종료된 경우, 맹목적으로 새 리드를 생성하지 마세요. 먼저 자체
requestId와 사이트 백엔드의 중복 제거 메커니즘을 사용하거나 CRM에서 생성된 리드를 찾으세요. - 이벤트 전송 오류가 리드 생성 결과를 확인하지 않고 사용자가 양식을 다시 제출하도록 해서는 안 됩니다.
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에서 결과 확인
통합 후 다음을 확인하세요:
- 리드가
GET /api/leads/{id}또는GET /api/leads/paged목록에 나타납니다. - 리드의 소유자, 작성자 및 생성 시간이 정확합니다.
- 마케팅 이벤트 응답의 첫 번째 전송 시
duplicate가false입니다. - 동일한 제출을 다시 전송하면
duplicate: true가 반환됩니다. - 마케팅 대시보드에서 데이터가 올바른 기간, 채널 및 캠페인에 나타납니다.
생성된 리드 가져오기
curl "$CRM_BASE_URL/api/leads/$LEAD_ID" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
목록 또는 조정을 위한 리드 가져오기
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 필터를 추가로 사용하세요.
Reactive CRM