> For the complete documentation index, see [llms.txt](https://docs.hackle.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hackle.io/en/development-guide/react/in-app-message/react-in-app-message-listener.md).

# In-App Message Event Listener

{% hint style="info" %}
This feature is supported in React SDK version 11.37.0 and above.
{% endhint %}

## Interfaces

### HackleInAppMessageListener

```typescript
interface HackleInAppMessageListener {
  beforeInAppMessageOpen?(inAppMessage: HackleInAppMessage): void
  afterInAppMessageOpen?(inAppMessage: HackleInAppMessage): void
  beforeInAppMessageClose?(inAppMessage: HackleInAppMessage): void
  afterInAppMessageClose?(inAppMessage: HackleInAppMessage): void
  onInAppMessageClick?(
    inAppMessage: HackleInAppMessage,
    view: HackleInAppMessageView,
    action: HackleInAppMessageAction
  ): boolean
}
```

#### onInAppMessageClick

You can control In-App Message behavior through the boolean value returned by the `onInAppMessageClick` method.

* Returning `true` overrides the existing In-App Message action.
  * For example, if the existing In-App Message click action was `Do not show for a day`, that action will not execute.
* Returning `false` keeps the existing In-App Message action as-is.

{% hint style="warning" %}
When calling `view.close()` inside `onInAppMessageClick`

If `view.close()` is called inside the listener, it is treated the same as returning `true`.

```typescript
onInAppMessageClick: (message, view, action) => {
  view.close();

  // return false를 하더라도 true한 것과 동일하게 처리됨.
  return false;

},
```

{% endhint %}

### HackleInAppMessage

```typescript
interface HackleInAppMessage {
  key: number
}
```

* Returns the key of the In-App Message.

### HackleInAppMessageView

```typescript
interface HackleInAppMessageView {
  close(): void
  inAppMessage: HackleInAppMessage // 11.48.0+
}

```

* You can directly close the In-App Message from within a listener function by calling `close()`.

### HackleInAppMessageAction

```typescript
type HackleInAppMessageActionType = "CLOSE" | "LINK"
type HackleInAppMessageActionLinkTarget = "CURRENT" | "NEW_TAB" | "NEW_WINDOW"

interface HackleInAppMessageAction {
  type: HackleInAppMessageActionType
  close?: {
    hideDurationMillis: number | null
  }
  link?: {
    url: string
    target: HackleInAppMessageActionLinkTarget
    shouldCloseAfterLink: boolean
  }
}
```

<table><thead><tr><th width="250">property</th><th>description</th></tr></thead><tbody><tr><td><code>close?.hideDurationMillis</code></td><td>When the action hides the message for a specific duration, returns that duration in milliseconds.</td></tr><tr><td><code>link?.url</code></td><td>Returns the link when a link is included. e.g) https://hackle.io</td></tr><tr><td><code>link?.target</code></td><td><code>NEW_TAB</code> when navigating to a new tab<br><code>NEW_WINDOW</code> when navigating to a new window<br><code>CURRENT</code> when navigating in the current tab</td></tr><tr><td><code>link?.shouldCloseAfterLink</code></td><td>Returns true when the close after link option is <code>ON</code>.</td></tr></tbody></table>

## Usage Example

### Register Listener

The example is written inside `useEffect`, but you can place it wherever it suits your use case.

```typescript
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
// import hackleClient
import { hackleClient } from "./hackleClient";

export default function Example() {
  const navigate = useNavigate();

  useEffect(() => {
    hackleClient.setInAppMessageListener({
      onInAppMessageClick: (message, view, action) => {
        // 100번 키의 인앱메시지에 대하여 대시보드에서 설정한 link URL을 React의 Route 로직으로 대체합니다.
        if (message.key === 100) {
          if (action.link?.url) {
            view.close()
	          navigate(action.link.url);
            return true;
          }
        }

        return false;
      },
      afterInAppMessageClose(message) {
        console.log("afterInAppMessageClose", message);
      },
      afterInAppMessageOpen(message) {
        console.log("afterInAppMessageOpen", message);
      },
      beforeInAppMessageClose(message) {
        console.log("before view close", message);
      },
      beforeInAppMessageOpen(message) {
        console.log("before view open", message);
      },
    });
  }, [navigate]);

  return;
}

```

### Unregister Listener

```javascript
hackleClient.setInAppMessageListener(null);
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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/en/development-guide/react/in-app-message/react-in-app-message-listener.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.
