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

# Writing Custom Code in Embeddables

> How to get the most out of custom code blocks in Embeddables

Custom Code blocks in Embeddables are where you can escape the confines of no-code and create entirely custom functionality.

Custom Code exists in two main places: [Computed Fields](#computed-fields) and [Actions](#actions).

<CodeGroup>
  ```javascript Example Computed Field theme={null}
  function result(userData, helperFunctions, triggerContext) {
    ...
  }
  ```

  ```javascript Example Action theme={null}
  function output(userData, helperFunctions, triggerContext) {
    ...
  }
  ```
</CodeGroup>

### Available arguments in Custom Code functions

Custom Code blocks provide various bits of context through arguments in the root functions. They are, in order:

| # | Argument          | Description                                                                                                                  |
| - | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| 1 | `userData`        | The current User Data                                                                                                        |
| 2 | `helperFunctions` | An object containing various helper functions (see [full list below](#available-helper-functions))                           |
| 3 | `triggerContext`  | An object containing data on what triggered the Computed Field or Action (see [full list below](#available-trigger-context)) |

## Helper Functions

The following helper functions are available in both Computed Fields and Actions through the `helperFunctions` argument:

### Page Navigation Functions

<AccordionGroup>
  <Accordion title="goToNextPage()">
    Navigates to the next page in the flow.

    This is useful when you want to navigate to the next page in the flow, but don't want to use the default navigation logic.

    ```javascript theme={null}
    // Example usage
    await helperFunctions.goToNextPage();
    ```
  </Accordion>

  <Accordion title="goToPrevPage()">
    Navigates to the previous page in the flow.

    This is useful when you want to navigate to the previous page in the flow, but don't want to use the default navigation logic.

    ```javascript theme={null}
    // Example usage
    await helperFunctions.goToPrevPage();
    ```
  </Accordion>

  <Accordion title="goToPage(page: object)">
    Navigates to a page. Pass an object with **one** of the following properties:

    * **`key`** (string) — the page key
    * **`id`** (string) — the page id
    * **`index`** (number) — the page index (1-based)
    * **`idOrKey`** (string) — accepts either a page id or a page key

    ```javascript theme={null}
    // Example usage
    helperFunctions.goToPage({ key: 'page_key_1234567890' });
    helperFunctions.goToPage({ id: 'page-test-id' });
    helperFunctions.goToPage({ index: 2 });
    helperFunctions.goToPage({ idOrKey: 'page_key_1234567890' }); // works with id or key
    ```
  </Accordion>
</AccordionGroup>

### Data Management Functions

<AccordionGroup>
  <Accordion title="getUserData()">
    Returns the current [User Data](/features/user-data) from the flow controller.

    This is useful when you need to read the current state of User Data, as opposed to the initial userData value that was passed in as the first argument.

    ```javascript theme={null}
    // Example usage
    const currentData = helperFunctions.getUserData();
    ```
  </Accordion>

  <Accordion title="setUserData(key: string, value: any)">
    Updates a specific key/value pair in the [User Data](/features/user-data).

    ```javascript theme={null}
    // Example usage
    helperFunctions.setUserData('userName', 'John');
    ```
  </Accordion>

  <Accordion title="setUserData(updates: Record<string, unknown>)">
    Updates multiple fields in the User Data at once.

    Accepts an object containing key/value pairs to update - i.e. to merge into the existing User Data.

    Note that nested objects will be replaced entirely, not merged.

    ```javascript theme={null}
    // Example usage
    helperFunctions.setUserData({
      userName: 'John',
      age: 30,
      preferences: { theme: 'dark' }
    });
    ```
  </Accordion>

  <Accordion title="resetUserData()">
    Resets all User Data to its initial state, effectively starting fresh.

    Use with caution as this will clear all previously stored User Data.

    ```javascript theme={null}
    // Example usage
    helperFunctions.resetUserData();
    ```
  </Accordion>
</AccordionGroup>

### Component and UI Functions

<AccordionGroup>
  <Accordion title="getComponentElement(key: string)">
    Returns the DOM element for a component with the specified key.

    Useful for direct DOM manipulation, accessing element properties (such as `value` for a password input field), or setting up custom event listeners.

    ```javascript theme={null}
    // Example usage
    const element = helperFunctions.getComponentElement('submit_button');
    element.disabled = true;
    ```
  </Accordion>

  <Accordion title="openInfoBox(infoBoxPageKey: string)">
    Opens an info box with the specified page key.

    The page key must refer to a page which is designed to be shown within an info box.

    Returns a Promise that resolves when the info box is opened.

    ```javascript theme={null}
    // Example usage
    await helperFunctions.openInfoBox('infobox_faqs_popup_page');
    ```
  </Accordion>

  <Accordion title="closeInfoBox()">
    Closes the currently open info box. Returns a Promise that resolves when the info box is closed.

    ```javascript theme={null}
    // Example usage
    await helperFunctions.closeInfoBox();
    ```
  </Accordion>
</AccordionGroup>

### Action and Flow Control

<AccordionGroup>
  <Accordion title="triggerAction(actionId: string)">
    Programmatically triggers an action by its ID.

    Returns a Promise that resolves when the action is complete.

    Useful for chaining actions or conditional action execution.

    ```javascript theme={null}
    // Example usage
    await helperFunctions.triggerAction('action_aaaaaaaaaaaa');
    ```
  </Accordion>

  <Accordion title="triggerValidation()">
    Triggers form validation on the flow controller.

    Useful when you need to validate form inputs programmatically.

    ```javascript theme={null}
    // Example usage
    helperFunctions.triggerValidation();
    ```
  </Accordion>
</AccordionGroup>

### Analytics and Events

<AccordionGroup>
  <Accordion title="trackCustomEvent(customEventName: string, customEventProps: any)">
    Tracks a custom analytics event with the given name and properties.

    Returns a `Promise<void>` that resolves once the event has been sent. You can `await` it if you need to wait for the event to be delivered before continuing (for example, before navigating away).

    ```javascript theme={null}
    // Example usage — fire and forget
    helperFunctions.trackCustomEvent('button_clicked', {
      buttonId: 'submit',
      timestamp: Date.now()
    });

    // Example usage — await before navigating
    await helperFunctions.trackCustomEvent('purchase_completed', {
      orderId: userData.order_id
    });
    await helperFunctions.goToNextPage();
    ```
  </Accordion>
</AccordionGroup>

### Additional Helpers

<AccordionGroup>
  <Accordion title="helpers">
    An object containing various utility helper functions. The exact available helpers depend on the context and implementation.

    ```javascript theme={null}
    // Example usage
    const { formatDate, validateEmail } = helperFunctions.helpers;
    ```
  </Accordion>
</AccordionGroup>

## Trigger Context variables

<CodeGroup>
  ```typescript Trigger Context for Computed Fields theme={null}
  type TriggerContext = {
    inputs_causing_recompute: string[]; // List of keys of inputs that caused the recompute
    old_input_values: string[]; // List of old values of those inputs (last time this Computed Field was computed)
    new_input_values: string[]; // List of current values of those inputs
    old_user_data: Record<string, unknown>; // Snapshot of User Data from when this Computed Field was last computed
    new_user_data: Record<string, unknown>; // Current value of User Data (identical to the first userData argument)
  };
  ```

  ```typescript Trigger Context for Actions theme={null}
  type TriggerContext = {
    trigger_type: string; // E.g. 'outputs_onclick'
    trigger_page_id: string; // The page that triggered the Action (if triggered by page change)
    trigger_page_key: string; // The page that triggered the Action (if triggered by page change)
    trigger_component_id: string; // The component that triggered the Action (if triggered by a component)
    trigger_component_key: string; // The component that triggered the Action (if triggered by a component)
  };
  ```
</CodeGroup>

<Note>
  **Please note** that `old_user_data` and `new_user_data` currently only
  contain the input keys for the Computed Field, not all of User Data. This may
  change in the future.
</Note>
