> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tight.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Listeners

> Observe and intercept actions taken inside the Tight Embeddable UI

## Overview

Event listeners are used to observe and intercept actions taken inside the Embeddable UI. You might, for example,
react to a user linking a bank account, or take over the library's built-in behavior entirely.

Listeners are shared across all instances of the Embeddable UI. Registrations across different components share the
same state, and the last registration for a given key wins, so prefer a single registration site per event key to
avoid conflicts.

The available events are listed below under [Reference](#reference).

## Use Cases

Event listeners open up a wide range of possibilities for tailoring the Embeddable UI to your platform. The examples
below illustrate some common patterns.

### Invoice Routing

If your platform has its own invoicing, event listeners let you route users back to your invoices from within the
Embeddable UI. For example, a vertical SaaS platform issues invoices through its own product, and the Tight
[Transactions Dashboard](/embeddable-ui/react/bank-transactions/transactions-dashboard) shows a payout that includes three of those invoices. When the user clicks on one of those
invoices, you can intercept the click and route the user to the corresponding invoice in your platform instead.

### Paywall Enforcement

Event listeners also let you gate specific functionality behind your own pricing tiers. For example, a horizontal SaaS
platform wants to offer Tax Estimates only on a paid plan. When a user clicks into tax-related functionality,
the platform intercepts the routing and shows its own paywall screen instead of the built-in tax experience.

## Setting Listeners

Listeners are accessed via the `useEmbeddedEventListeners` hook. Keep in mind that this must be used within a `<Tight>`
component. Listener declaration is done either by passing initial listeners to the hook, or by using the `setListeners`
function returned by it. This function accepts a subset of all possible listeners, and will merge any input into your
already defined listeners. This means that both this:

```TypeScript theme={null}
import { useEmbeddedEventListeners } from "@tight-embedded/react";
// ...
const [listeners, setListeners] = useEmbeddedEventListeners({
  plaidLink: {
    listener: (event) => {
      if (event.result === "SUCCESS") {
        console.log("Bank linked:", event.type);
      }
    },
  },
});
```

and this:

```TypeScript theme={null}
import { useEmbeddedEventListeners } from "@tight-embedded/react";
// ...
const [listeners, setListeners] = useEmbeddedEventListeners();
setListeners({
  plaidLink: {
    listener: (event) => {
      if (event.result === "SUCCESS") {
        console.log("Bank linked:", event.type);
      }
    },
  },
});
```

are valid methods of defining the same set of listeners.

<Note>
  The initial listeners passed to `useEmbeddedEventListeners` are only applied once, on mount. Re-renders do not
  re-apply them. To update a listener after mount, use `setListeners`.
</Note>

### Updating Listeners

Since `setListeners` accepts a subset of listeners, you're able to update your listeners at any time after mount. The
code below adds a `gusto` listener without affecting any previously registered keys.

```TypeScript theme={null}
setListeners({
  gusto: { listener: handleGusto, preventDefault: true },
});
```

Note that listener merging is a *shallow merge* - input is only merged at the top level.

### Removing Listeners

If you want to remove a listener, pass `null` for its key. Unrelated keys are preserved.

```TypeScript theme={null}
setListeners({ gusto: null });
```

### Preventing Default Behavior

Each listener is registered as an `EventRegistration`, which pairs your callback with an optional `preventDefault`
flag. When `preventDefault` is `true`, the library's built-in behavior for that event is suppressed (for example, the
Plaid modal will not open; the transaction drawer will not open). When `false` or omitted, both your listener and the
default behavior run.

For example, to open a bank's website in a custom in-app browser instead of a new tab, suppress the default behavior
and handle the navigation yourself:

```TypeScript theme={null}
setListeners({
  plaidLink: {
    preventDefault: true,
    listener: (event) => {
      if (event.type === "PLAID_LINK_ROUTE_TO_BANK" && event.result === "SUCCESS") {
        openInAppBrowser(event.data.bankUrl);
      }
    },
  },
});
```

### Handling Events

Every event is a discriminated union with a `result` field:

```TypeScript theme={null}
type TightEvent<T, D, E> =
  | { type: T; result: "SUCCESS"; data: D;    error: null }
  | { type: T; result: "FAILURE"; data: null; error: E    }
```

Always branch on `event.result` before reading `data` or `error`.

```TypeScript theme={null}
listener: (event) => {
  if (event.result === "SUCCESS") {
    // event.data is typed
  } else {
    // event.error is typed
  }
}
```

## Reference

`useEmbeddedEventListeners` returns a `[listeners, setListeners]` tuple:

<ResponseField name="listeners" type="object">
  A snapshot of all currently registered listeners.
</ResponseField>

<ResponseField name="setListeners" type="function">
  A function to merge new registrations into the existing state. Each key accepts an `EventRegistration`, or `null`
  to remove that listener.

  <Expandable title="EventRegistration">
    <ParamField body="listener" type="function">
      The callback fired when the event occurs.
    </ParamField>

    <ParamField body="preventDefault" type="boolean" default="false" post={["optional"]}>
      Whether or not the library's built-in default behavior for this event should be suppressed. When `false`
      or omitted, both your listener and the default behavior run.
    </ParamField>
  </Expandable>
</ResponseField>

### Events

Each row below is a registration key you can pass to `useEmbeddedEventListeners`. The **Event types** column lists the `event.type` values a single registration may receive, and the data and error shapes are the payloads on `SUCCESS` and `FAILURE` results respectively.

| Registration key           | Description                                                                                                                                                                                                                                                                | Event types, data, and error shapes                                                                                                                                                                                                                                                                                                                                       |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `plaidLink`                | Fires at the start of each bank-linking action; a single registration handles all lifecycle types. `preventDefault: true` prevents the Plaid modal from opening, letting you manage the flow yourself.                                                                     | Types: `PLAID_LINK_NEW`, `PLAID_LINK_RESET`, `PLAID_LINK_RELINK`, `PLAID_LINK_UNLINK`, `PLAID_LINK_ROUTE_TO_BANK`. Data on `SUCCESS`: `{ plaidAccessToken: string } \| null` (reset/relink/unlink), `{ bankUrl: string }` (route to bank), or `null` (new). Error on `FAILURE`: `{ errorCode: string }`.                                                                  |
| `plaidLinkEvent`           | Fires for every event emitted by the Plaid SDK during the link flow. Useful for analytics.                                                                                                                                                                                 | Type: `PLAID_LINK_EVENT`. Data on `SUCCESS`: `{ eventName: string; metadata: unknown }`.                                                                                                                                                                                                                                                                                  |
| `plaidLinkError`           | Fires when the Plaid flow encounters an error or the user exits with an error.                                                                                                                                                                                             | Type: `PLAID_LINK_FAILURE`. Error on `FAILURE`: `{ displayMessage: string; errorCode: string; errorMessage: string }`.                                                                                                                                                                                                                                                    |
| `gusto`                    | Fires when the user taps "Connect Gusto" in the Banks & Integrations section. `preventDefault: true` suppresses the built-in Gusto OAuth flow so you can initiate OAuth from your own backend.                                                                             | Type: `GUSTO_NEW`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                                                                                                                                             |
| `conversations`            | Fires when the user opens or starts a conversation. `preventDefault: true` suppresses the library's conversation drawer.                                                                                                                                                   | Type: `OPEN_CONVERSATION`. Data on `SUCCESS`: `ConversationGetDto` (existing conversation), `{ defaultValues: MessageFormValues }` (new conversation with pre-filled text), or `null` (blank new conversation).                                                                                                                                                           |
| `transactionForm`          | Fires when a transaction form opens or closes; delineates between transactions from processor (ie. Stripe, Square, etc.) and non-processor sources. `preventDefault: true` on open prevents the library's transaction drawer from opening, letting you render your own UI. | Types: `OPEN_BANK_TRANSACTION_FORM`, `CLOSE_BANK_TRANSACTION_FORM`, `OPEN_PROCESSOR_TRANSACTION_FORM`, `CLOSE_PROCESSOR_TRANSACTION_FORM`. Data on `SUCCESS`: `BankTransaction` (editing), `null` (creating), or `BankTransaction \| null` (close). Error on `FAILURE`: `Record<string, unknown>`.                                                                        |
| `bITile`                   | Financial dashboard tiles. Fires when a dashboard tile mounts. Useful for tracking which tiles are visible. `preventDefault` has no effect on tile events.                                                                                                                 | Types: `CASH_FLOW_TILE`, `EXPENSE_TILE`, `PROFIT_AND_LOSS_TILE`. Result: `SUCCESS` when the corresponding tile mounts.                                                                                                                                                                                                                                                    |
| `bill`                     | Bill drawer. Fires when the user opens a bill.                                                                                                                                                                                                                             | Type: `OPEN_BILL`. Data on `SUCCESS`: `BillGetDto`. Error on `FAILURE`: `Record<string, unknown>`.                                                                                                                                                                                                                                                                        |
| `customer`                 | Customer selector/form. Fires when the user opens the customer selector or form.                                                                                                                                                                                           | Type: `OPEN_CUSTOMER`. Data on `SUCCESS`: `CustomerGetDto` (existing customer) or `null` (new customer).                                                                                                                                                                                                                                                                  |
| `payroll`                  | Payroll record. Fires when the user opens a payroll record.                                                                                                                                                                                                                | Type: `OPEN_PAYROLL`. Data on `SUCCESS`: `{ data: PayrollGetDto }`.                                                                                                                                                                                                                                                                                                       |
| `taxDashboardZeroStateCTA` | Fires when the user clicks the zero-state call to action on the Tax Dashboard.                                                                                                                                                                                             | Type: `TAX_DASH_CTA`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                                                                                                                                          |
| `taxProfileCTA`            | Fires when the user clicks the tax profile call to action on the Tax Dashboard or Financial Overview.                                                                                                                                                                      | Type: `TAX_PROFILE_CTA`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                                                                                                                                       |
| `taxFilingCTA`             | Fires when the user clicks a tax filing call to action on the Tax Dashboard.                                                                                                                                                                                               | Type: `TAX_FILING_CTA`. Data on `SUCCESS`: `{ action: "CONTINUE" \| "VIEW" \| null }`.                                                                                                                                                                                                                                                                                    |
| `learnMore`                | Fires when the user clicks a "Learn more" link within the import flows.                                                                                                                                                                                                    | Types: `IMPORT_CSV_LEARN_MORE`, `IMPORT_RULES_LEARN_MORE`, `SCRIPT_BLOCKER_LEARN_MORE`, `IMPORT_XERO_LEARN_MORE`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                                              |
| `paymentProcessorTutorial` | Fires when the user opens the payment processor tutorial from the Invoice Dashboard or Financial Overview.                                                                                                                                                                 | Type: `PAYMENT_PROCESSOR_TUTORIAL`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                                                                                                                            |
| `paymentProcessing`        | Fires for payment processing actions, such as refunding an invoice from the Invoice Dashboard or setting up payment processing. Also registered under the `invoice` alias.                                                                                                 | Types: `REFUND_INVOICE`, `SETUP_PAYMENT_PROCESSING`. Data on `SUCCESS`: `{ invoiceId: string }` (refund) or `null` (setup).                                                                                                                                                                                                                                               |
| `renderClientInvoice`      | Fires when a client pays an invoice from the client-facing invoice view.                                                                                                                                                                                                   | Type: `PAY_INVOICE`. Data on `SUCCESS`: `{ invoiceId: string; invoiceName: string; invoiceBalance: number }`.                                                                                                                                                                                                                                                             |
| `incomeDashCTA`            | Fires when the user clicks the send invoice call to action on the Income Dashboard.                                                                                                                                                                                        | Type: `SEND_INVOICE`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                                                                                                                                          |
| `accountantUserAction`     | Fires when an accountant takes an action on a user.                                                                                                                                                                                                                        | Type: `ACCOUNTANT_USER_ACTION`. Data on `SUCCESS`: `{ value: string; userId: string }`.                                                                                                                                                                                                                                                                                   |
| `accountant`               | Fires when members or teammates are added, updated, removed, or restored.                                                                                                                                                                                                  | Types: `ADD_MEMBERS`, `UPDATE_MEMBERS`, `REMOVE_MEMBERS`, `RESTORE_MEMBERS`, `ADD_TEAMMATE`, `UPDATE_TEAMMATE`, `REMOVE_TEAMMATE`, `RESTORE_TEAMMATE`. Data on `SUCCESS`: `{ users: Array<{ id: string; userId: string; email?: string }> }` (member types), `{ teammate: object }` (add/update teammate), or `{ id: string; userId: string }` (remove/restore teammate). |
| `import`                   | Fires when an import flow completes.                                                                                                                                                                                                                                       | Types: `IMPORT_EXPENSE_RULES_COMPLETED`, `IMPORT_QBO_COMPLETED`, `IMPORT_XERO_COMPLETED`, `IMPORT_BENCH_COMPLETED`, `IMPORT_WAVE_COMPLETED`. Data on `SUCCESS`: `null`.                                                                                                                                                                                                   |

### TypeScript

All types are exported from `@tight-embedded/react`:

```TypeScript theme={null}
import type {
  TightEvent,
  TightEventListener,
  TightEvents,
  EventRegistration,
  PlaidLinkEvent,
  UseEmbeddedEventListenersResult,
} from "@tight-embedded/react";
```
