커넥티드 콘텐츠 (Connected Content) 작성하기
메시지를 보내는 그 순간, 외부 API에서 실시간 데이터를 가져와 본문에 끼워 넣는 기능입니다. 잔여 포인트, 오늘의 쿠폰, 개인화 추천 상품처럼 Hackle에 저장돼 있지 않은 정보를 메시지에 활용할 수 있습니다.
비개발자를 위한 커넥티드 콘텐츠 작성 방법
코드를 직접 쓸 필요는 없습니다. 메시지 편집기의 {...} 개인화 변수 추가 버튼을 누르면, 폼만 채우는 방식으로 {% connected_content %} 태그가 자동으로 만들어집니다.
시작 전 준비물 (개발팀에서 받아 두세요)
호출할 API 주소(
https://로 시작)요청 방식(GET 또는 POST)
응답 예시(JSON) - 어떤 필드를 메시지에 쓸 수 있는지 확인용
먼저 메시지 편집기에서 {...} 버튼 클릭 → "커넥티드 콘텐츠" 탭 선택하세요
모달이 열리면 상단에서 속성 / 커넥티드 콘텐츠 중 "커넥티드 콘텐츠 — 외부 API에서 실시간 데이터"를 선택합니다.

STEP 1. API URL 입력 후 API 테스트 클릭
API URL을 입력합니다. 인증 헤더나 POST 본문이 필요하면 요청 옵션을 펼쳐 입력합니다. URL에는 {{user_properties["id"]}} 같은 개인화 변수도 그대로 끼워 넣을 수 있습니다. 그다음 API 테스트 버튼을 눌러 실제 응답이 잘 오는지, 어떤 필드가 포함되어 있는지 미리 확인합니다.

STEP 2. 메시지에 넣을 값 선택 + 변수명 입력
응답 결과에서 메시지에 노출할 필드(예: code, discount)를 체크합니다. 그리고 **응답 변수명(:save)**에 사용할 이름(예: product)을 입력합니다. 이 이름이 곧 본문에서 값을 꺼내 쓸 때 사용할 변수가 됩니다.

STEP 3. 저장하기 클릭 → 본문에서 변수 클릭으로 삽입
저장하기를 누르면 모달이 만든 변수가 "사용할 수 있는 변수" 목록에 추가됩니다. 본문 원하는 위치에 커서를 두고 해당 변수를 클릭하면 {{coupon.code}}처럼 자동 삽입됩니다.

기본 문법
<URL>(필수): 호출할 외부 엔드포인트의 절대 URL.https://만 허용됩니다.:method: HTTP 메서드.GET/POST만 지원, 기본값GET.:body: POST 요청 본문. JSON 객체 문자열 형태로 작성해야 합니다.:headers: 요청 헤더. JSON 객체 문자열 형태로 작성해야 하며, 값은 모두 문자열이어야 합니다. 지정하지 않으면Content-Type: application/json이 기본 적용됩니다.:save: 응답 JSON을 담을 변수 이름. 이후{{변수.필드}}형태로 메시지에서 꺼내 쓸 수 있습니다. 지정하지 않으면 응답을 사용할 수 없습니다.
URL, body, headers의 값에
{{user_properties["name"] | default: "고객님"}},{{event_properties["campaign_id"] | default: "1"}}같은 개인화 변수를 자유롭게 사용 할 수 있습니다.

파라미터
URL
반드시 절대 URL이며
https://스킴만 허용합니다.공인 IP로 해석되는 최종 URL만 호출할 수 있습니다.
:method
지원:
GET,POST, 기본값GET그 외 메서드(
PUT,DELETE,PATCH등)는 거부되고 태그가 통째로 스킵됩니다.
:body
:method POST일 때 사용합니다.GET에서는 무시됩니다.인라인 JSON을 그대로 적을 수 있습니다. 예:
:body {"foo":"bar"}
:headers
반드시 JSON 객체 문자열이어야 하고 모든 값은 문자열이어야 합니다.
좋은 예:
:headers {"Authorization":"Bearer abc","X-Trace":"123"}잘못된 예:
:headers {"Retry": 3}(값이 숫자) → 검증 실패로 태그 스킵
Content-Type: application/json타입만을 지원하며, 명시하지 않아도 기본값으로 자동 적용됩니다.
:save
응답 JSON 객체를 이 이름의 변수로 컨텍스트에 저장합니다.
같은 템플릿 안의 이후 태그/Output 노드 모두에서 참조 가능합니다. 예를 들어 첫 번째
connected_content의 결과를 두 번째connected_content의 URL이나 body에 다시 사용할 수 있습니다.응답이 JSON 객체가 아니거나 비어 있으면 빈 값으로 저장됩니다(렌더링 시 빈 문자열).
예제
1. 가장 단순한 GET 호출
응답이 {"name":"운동화","price":59000}이라면 → 운동화 59000원
2. URL에 사용자/이벤트 변수 끼워 넣기
event_properties.order_id = "ABC-123"이면 실제 호출 URL은 https://api.example.com/orders/ABC-123이 됩니다.
3. POST + JSON body
4. 인증 헤더가 필요한 호출
5. 중첩된 JSON 응답에서 값 꺼내기
응답 {"product":{"name":"티셔츠","brand":"Nike"}} → 티셔츠 by Nike
6. 태그 체이닝 (앞 호출 결과를 다음 호출에 사용)
7. POST + form-encoded 본문 + 커스텀 헤더
응답 처리 규칙
200 OK + JSON 객체
JSON을 파싱하여 :save 변수에 매핑. 필드는 {{var.field}} 또는 {{var["field"]}}로 접근
200 OK + JSON 배열 또는 원시값
JSON 객체가 아니므로 빈 값으로 처리
200 OK + 빈 본문
빈 값으로 처리
200이 아닌 모든 상태 코드 (4xx, 5xx, 3xx 등)
빈 값으로 처리 (리다이렉트 따라가지 않음)
응답 본문이 1MB 초과
빈 값으로 처리
네트워크 오류, 타임아웃
빈 값으로 처리
빈 값(empty) 으로 처리되었다는 것은
:save로 지정한 변수에 빈 맵이 저장되었다는 뜻입니다.{{var.anything}}은 빈 문자열로 렌더링되며, 이로 인해 메시지 발송 자체가 실패하지는 않습니다.
제약 사항과 보안 정책
보호 한도
URL 스킴
https://만 허용
호스트
공인 IP로 해석되는 호스트만 허용 (사내망 / 사설 대역 차단)
리다이렉트
따라가지 않음 (최종 URL을 직접 지정해야 함)
응답 본문 크기
최대 1MB (초과 시 빈 값 처리)
단일 호출 타임아웃
2초
한 메시지(Liquid render) 내부 누적 호출 시간
총 2초 (한도 초과 후 호출은 HTTP 호출 없이 스킵)
HTTP 메서드
GET, POST만
헤더 값 형식
JSON 객체 문자열, 값은 모두 문자열
실패 시 동작
Connected Content는 메시지 발송을 막지 않습니다. 모든 실패 케이스는 "default 값으로 대체" 됩니다.
대표 케이스:
URL이 비어 있거나 플래그-값 쌍이 맞지 않는 경우 → 태그 전체 스킵
:method에PUT같은 미지원 메서드를 지정 → 태그 스킵:headers가 유효한 JSON 객체 문자열이 아닌 경우 → 태그 스킵URL 검증 실패 (HTTPS 아님, 사설 IP 등) → 빈 응답
네트워크 오류, 200 외 응답, 본문 1MB 초과, JSON 객체 아님 → 빈 응답
한 메시지 내 누적 호출 시간 2초 초과 이후의 호출 → HTTP 호출 없이 스킵, 빈 응답
빈 응답이 저장된 변수를 메시지에서 사용해도 빈 문자열로 렌더링됩니다. 따라서 응답이 비어 있을 때를 대비해 다음과 같은 방어 코드를 곁들이는 것을 권장합니다.
자주 묻는 질문
Q. 한 메시지에 connected_content를 여러 번 써도 되나요?
가능합니다. 단, 한 메시지의 모든 connected_content 호출은 누적 2초의 시간 예산을 공유합니다. 첫 번째 호출이 1.8초 걸렸다면 두 번째 호출은 0.2초 안에 끝나야 하고, 그 사이에 한도를 초과하면 이후 호출은 네트워크 호출 없이 즉시 스킵됩니다. 외부 API의 평균 응답시간이 충분히 짧을 때만 다중 호출을 사용하세요.
Q. 응답이 JSON 배열일 때는 어떻게 접근하나요?
최상위가 배열이면 객체로 인식되지 않아 빈 값이 됩니다. API 측에서 {"items":[...]}처럼 객체로 감싼 형태로 내려주도록 하거나, 래핑 엔드포인트를 따로 두세요.
마지막 업데이트