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.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 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 theuseEmbeddedEventListeners 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:
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.Updating Listeners
SincesetListeners 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.
Removing Listeners
If you want to remove a listener, passnull for its key. Unrelated keys are preserved.
Preventing Default Behavior
Each listener is registered as anEventRegistration, 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:
Handling Events
Every event is a discriminated union with aresult field:
event.result before reading data or error.
Reference
useEmbeddedEventListeners returns a [listeners, setListeners] tuple:
A snapshot of all currently registered listeners.
A function to merge new registrations into the existing state. Each key accepts an
EventRegistration, or null
to remove that listener.Events
Each row below is a registration key you can pass touseEmbeddedEventListeners. 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: