# 인앱 메시지 JavaScript Bridge

{% hint style="warning" %}
본 문서에서 다루는 모든 메서드는 [HTML 기반으로 생성된 인앱 메시지](/crm-marketing/in-app-message-guide/html-message.md) 에서만 사용 가능한 JavaScript API입니다.
{% endhint %}

JavaScript Bridge는 HTML 인앱 메시지와 핵클의 SDK가 상호작용 하기 위한 도구입니다.

* 닫기 버튼을 클릭했을 때
* 링크를 이동할 때
* 캠페인의 전환에 해당하는 액션을 했을 때
* 인앱 메시지 내에서 핵클 기능 호출이 필요할 때

위와 같은 상황에서 JavaScript Bridge를 활용해 사용자 행동 추적 및 URL 이동 및 인앱 메시지 노출 여부를 제어할 수 있습니다.

## hackleBridgeReady

HTML 내에서 `Hackle.bridge` 가 사용 가능해질 때, `hackleBridgeReady` 이벤트가 발행됩니다.\
해당 이벤트 리스너의 콜백 안에서 `Hackle.bridge` 에 접근하는 것을 권장합니다.

`Hackle.bridge` 의 접근은 반드시 Ready 이벤트가 발생된 후 이루어져야 합니다.

#### 예제

```html
<button id="hackle-url">
	Go to Hackle
</button>
<script>
  window.addEventListener("hackleBridgeReady", function(){
    document.querySelector("#hackle-url").addEventListener("click", function(e) {
      Hackle.bridge.openUrl("https://hackle.io");
    });
	})
</script>
```

## URL 열기

인앱 메시지가 나타난 기기의 브라우저에서 URL을 열고 인앱 메시지를 닫습니다.

* 딥링크를 지원합니다.
* 클릭 이벤트는 추적하지 않습니다.

```typescript
Hackle.bridge.openUrl(url: string): void
Hackle.bridge.openUrl(url: HackleInAppMessageLink): void

interface HackleInAppMessageLink {
  url: string
  target: "CURRENT" | "NEW_TAB" | "NEW_WINDOW"
  shouldCloseAfterLink: boolean
}
```

<table><thead><tr><th width="205.21484375">target</th><th>설명</th></tr></thead><tbody><tr><td><code>CURRENT</code></td><td>현재 페이지에서 열기</td></tr><tr><td><code>NEW_TAB</code></td><td>새 탭에서 열기</td></tr><tr><td><code>NEW_WINDOW</code></td><td>새 창에서 열기</td></tr></tbody></table>

{% hint style="warning" %}
앱(Android, iOS, Flutter, React Native) 에서는 `CURRENT` 만 지원합니다.
{% endhint %}

#### 예제

현재 페이지에서 URL을 엳고 인앱 메시지를 닫습니다.

```html
<button id="hackle-url">
	Go to Hackle
</button>
<script>
  window.addEventListener("hackleBridgeReady", function(){
    document.querySelector("#hackle-url").addEventListener("click", function(e) {
      Hackle.bridge.openUrl("https://hackle.io");
    });
	})
</script>
```

#### 새 탭에서 열고 인앱 메시지 닫기

```html
<button id="hackle-url">
	Go to Hackle
</button>
<script>
  window.addEventListener("hackleBridgeReady", function(){
    document.querySelector("#hackle-url").addEventListener("click", function(e) {
      Hackle.bridge.openUrl({
        url: "https://hackle.io",
        target: "NEW_TAB",
				shouldCloseAfterLink: true
 			});
    });
	})
</script>
```

#### 새 창에서 열고 인앱 메시지 닫기

```html
<button id="hackle-url">
	Go to Hackle
</button>
<script>
  window.addEventListener("hackleBridgeReady", function(){
    document.querySelector("#hackle-url").addEventListener("click", function(e) {
      Hackle.bridge.openUrl({
        url: "https://hackle.io",
        target: "NEW_WINDOW",
				shouldCloseAfterLink: true
 			});
    });
	})
</script>
```

## 개인화

인앱 메시지 HTML에서는 유저 정보, 이벤트 정보를 이용하여 개인화된 메시지를 노출시킬 수 있습니다.

### 유저 프로퍼티 조회

트리거한 유저의 프로퍼티를 조회합니다.

```javascript
Hackle.bridge.getUser(): User
```

#### 예제

```javascript
const user = Hackle.bridge.getUser();
const props = user?.properties ?? {};
const age = props["age"] ?? -1;

if (age > 20) {
  document.getElementById("new-year-text").textContent 
    = `새 해에 ${age}를 맞이하신 고객님께만 드리는 특가 찬스!`;
}
```

### 트리거 이벤트 조회

인앱 메시지를 트리거한 이벤트 정보를 조회합니다.\
이벤트 키, 값, 프로퍼티 리스트 정보가 모두 포함됩니다.

```javascript
Hackle.bridge.getTriggerEvent(): HackleEvent | undefined
```

#### 예제

```javascript
const event = Hackle.bridge.getTriggerEvent();
const promoDate = event?.properties?.["promo_date"] ?? "11.29";
document.getElementById("period-text").textContent = promoDate + " FRI — 자정까지 특가 세일";
```

### 트리거 이벤트 프로퍼티 조회

인앱 메시지를 트리거한 이벤트의 프로퍼티 1개를 조회합니다.

```javascript
Hackle.bridge.getTriggerEventProperty(
    key: String, 
    defaultValue: string | number | boolean | Array<string | number>
): PropertyValue
```

#### 예제

```javascript
const promoDate = Hackle.bridge.getTriggerEventProperty("promo_date", "11.29");
document.getElementById("period-text").textContent = promoDate + " FRI — 자정까지 특가 세일";
```

## 사용자 행동 추적

### 클릭 추적하기

인앱 메시지 캠페인의 **전환**에 해당하는 클릭 이벤트를 추적할 수 있습니다.

`$in_app_action` 이벤트가 발생하며, 이 이벤트를 기반으로 핵클 대시보드에서 캠페인의 성과를 확인할 수 있습니다.

* [성과 측정 자세히 보기](/crm-marketing/in-app-message-guide/analyze-in-app-message.md)
* [인앱 메시지 이벤트 자세히 보기](/event-management/hackle-event.md)

```typescript
trackClick(elementId?: string): void
```

#### 예제

```html
<button id="hackle-conversion">
	Hackle Conversion
</button>
<script>
  window.addEventListener("hackleBridgeReady", function(){
    document.querySelector("#hackle-conversion").addEventListener("click", function(e) {
      Hackle.bridge.trackClick("main-funnel-user-conversion-1");
    });
	})
</script>
```

![elementId가 $in\_app\_action 이벤트 속성으로 추가된 모습](/files/lP5Bf7u0ONArHwDEk7CO)

### 링크 클릭과 클릭 추적을 동시에 처리하기

링크 클릭 자체를 전환으로 간주하는 경우 URL 여는 것과 링크 클릭 이벤트 수집을 동시에 처리합니다.

```typescript
handleUrl(url: string | HackleInAppMessageLink, elementId?: string): void
```

#### 예제

```html
<button id="hackle-link">
	Hackle Link
</button>
<script>
  window.addEventListener("hackleBridgeReady", function(){
    document.querySelector("#hackle-link").addEventListener("click", function(e) {
      Hackle.bridge.handleUrl("https://hackle.io","main-funnel-user-conversion-1");
    });
	})
</script>
```

### 이벤트 전송

이벤트를 전송합니다.\
기존 [JavaScript SDK에서 이벤트를 전송하는 방식](/development-guide/javascript/event-tracking.md)과 동일합니다.

#### 예제

```html
<button id="custom-btn">X</button>
<script>
  window.addEventListener("hackleBridgeReady", () => {
    const closeButton = document.querySelector("#custom-btn");

    const event = {
      key: "purchase",
      properties: {
        pay_method: "CARD",
        discount_amount: 800,
        is_discount: true
      }
    };

    closeButton.addEventListener("click", () => {
      Hackle.bridge.track(event);
    });
})
</script>
```

## 인앱 메시지 닫기

인앱 메시지를 닫습니다.

```typescript
closeInAppMessage(hideDuration?: boolean | number): void
```

<table><thead><tr><th width="220.390625">hideDuration</th><th>설명</th></tr></thead><tbody><tr><td><code>true</code></td><td>하루 동안 숨김</td></tr><tr><td><code>false</code></td><td>즉시 닫기</td></tr><tr><td><code>number</code></td><td>전달한 분(minute) 동안 숨김</td></tr><tr><td><code>null / undefined</code></td><td>즉시 닫기</td></tr></tbody></table>

#### 예제

```html
<button id="close-btn">X</button>
<button id="hide-today-btn">오늘 하루 보지 않기</button>
<button id="hide-10m-btn">10분 동안 보지 않기</button>

<script>
  window.addEventListener("hackleBridgeReady", () => {
    const closeButton = document.querySelector("#close-btn");
    const hideTodayButton = document.querySelector("#hide-today-btn");
    const hide10mButton = document.querySelector("#hide-10m-btn");

    closeButton.addEventListener("click", () => {
      Hackle.bridge.closeInAppMessage();
    });

    hideTodayButton.addEventListener("click", () => {
      Hackle.bridge.closeInAppMessage(true);
    });

    hide10mButton.addEventListener("click", () => {
      Hackle.bridge.closeInAppMessage(10);
    });
  });
</script>
```

{% hint style="info" %}
HTML 인앱 메시지 템플릿을 사용해서 빠르게 시작해보세요.

복사 붙여넣기만으로 바로 이용할 수 있는 [HTML 인앱 메시지 템플릿](/crm-marketing/in-app-message-guide/html-message/in-app-message-html-template.md)을 제공합니다.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hackle.io/crm-marketing/in-app-message-guide/html-message/in-app-message-html-javascript-bridge.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
