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

# Introduction

> Embed the Reach Marketing Platform in your application as a React Component

You can also use our Reach React Library to embed Reach into your application.

<Note>
  You can see an example Github repository for a React application that uses this library [here](https://github.com/EmbedReach/reach-react-example).
</Note>

<Note>
  We currently only support React 18.
</Note>

## Install the library

```bash theme={null}
npm install @embedreach/components
```

## Initialize the library

Start by importing our css styles at the top of your application:

```javascript theme={null}
import "@embedreach/components/styles.css";
```

Now to integrate Reach components into your application, wrap them with the `ReachProvider` component. The provider requires a `config` object that initializes the Reach SDK with authentication and tenant configuration.

```javascript theme={null}
const config = {
  theme: {
    ...
  },
  authToken: 'your-auth-token',
  callbacks: {
    onReauthRequested: async () => {
      // return your auth token
      const token = ''
    },
  },
}


<ReachProvider {...config}>
  ...
</ReachProvider>
```

<Note>
  Please see [Authentication](/embeddable-ui/authentication) for more information on how to generate an auth token.
</Note>

<Note>
  If your app enforces security headers like Content Security Policy (CSP) or Cross-Origin Opener Policy (COOP), see [Security Headers (CSP & COOP)](/embeddable-ui/security-headers) for required configurations.
</Note>

<Note>
  Please see [Customization](/embeddable-ui/iframe/customization) for more information on how to customize the components.
</Note>

## Customization

We support the following customization options:

* [Color Customization](/embeddable-ui/iframe/customization#color-format-support)
* [Language Customization](/embeddable-ui/iframe/customization#language)

## Components Available

#### SegmentBuilderDialog

We expose a dialog component that can be used to create and edit segments.

```javascript theme={null}
<SegmentBuilderDialog
  /**
   * Control the open state of the dialog
   */
  open: boolean;
  setOpen: (open: boolean) => void;

  /**
   * Optional callback when the segment builder is closed
   * @param createdSegment - The created segment id or false if the segment was not created, 'error' if there was an error
   */
  onSegmentUpdated?: (createdSegment: string | false | 'error') => void;

  /**
   * Optionally pass in a segmentId to edit an existing segment
   */
  segmentId?: string;
/>
```

#### CreateAutomationDialog

This is the initial modal that can be used to create a new automation.

```javascript theme={null}
<CreateAutomationDialog
  /**
   * Optional callback when the segment builder is closed
   * @param createdAutomation - The created automation id or false if the automation was not created, 'error' if there was an error
   */
  onClose?: (createdAutomation: string | false | 'error') => void;

/**
   * Optionally skip the selection of automation and jump to the automation type
   * Currently only supports one time automation
   *
   * @Note This will remove the ability to select the automation type (e.g. the user will not be able to change the automation type)
   */
  automationType?: AutomationTriggerType.ONE_TIME;

  /**
   * Optional function to return extra merge fields for the automation
   */
  getExtraMergeFields?: () => Promise<ReachMergeField[]>;

  /**
   * Optional text and hyperlink to display for
   * replyTo settings
   */
  replyToSettingsText?: string;
  replyToSettingsLink?: string;

  /**
   * Optional text and hyperlink to display for
   * from name settings
   */
  fromNameSettingsText?: string;
  fromNameSettingsLink?: string;

  /**
   * Optional function to call prior to scheduling if a user wants to implement custom
   * logic to block scheduling
   *
   * @param args.estimatedEmailRecipients - The estimated number of email recipients
   * @param args.estimatedSmsRecipients - The estimated number of sms recipients
   * @param args.scheduleSendAt - The scheduled send time as an ISO date string, or null if not set
   *
   * @returns true if the automation should be scheduled, string otherwise that will be displayed to the user in a toast notification
   */
  onBeforeSchedule?: (args: {
    estimatedEmailRecipients: number;
    estimatedSmsRecipients: number;
    scheduleSendAt: string | null;
  }) => Promise<true | string>;
/>
```

#### ViewAutomationModal

This is the component used to view and edit automations. This components allows users to preview communications, edit automation details and view statistics on sent communications.

```javascript theme={null}
<ViewAutomationModal
 /**
   * The id of the automation to view
   */
  automationId?: string;

  /**
   * Optional function to return extra merge fields for the automation
   */
  getExtraMergeFields?: () => Promise<ReachMergeField[]>;

  /**
   * Optional callback when a duplication is created
   */
  onDuplicationCreated?: (duplicationId: string) => void;

  /**
   * Optional boolean to hide features
   */
  hideSms?: boolean;
  hideSales?: boolean;

  /**
   * Optional text and hyperlink to display for
   * replyTo settings
   */
  replyToSettingsText?: string;
  replyToSettingsLink?: string;

  /**
   * Optional text and hyperlink to display for
   * from name settings
   */
  fromNameSettingsText?: string;
  fromNameSettingsLink?: string;

  /**
   * Optional function to call prior to scheduling if a user wants to implement custom
   * logic to block scheduling
   *
   * @param args.estimatedEmailRecipients - The estimated number of email recipients
   * @param args.estimatedSmsRecipients - The estimated number of sms recipients
   * @param args.scheduleSendAt - The scheduled send time as an ISO date string, or null if not set
   *
   * @returns true if the automation should be scheduled, string otherwise that will be displayed to the user in a toast notification
   */
  onBeforeSchedule?: (args: {
    estimatedEmailRecipients: number;
    estimatedSmsRecipients: number;
    scheduleSendAt: string | null;
  }) => Promise<true | string>;
/>
```

#### SMSOnboarding

This is the component used to onboard a business to SMS. As long as you wrap the component with the `ReachProvider` component, it will automatically update based on the state of the business's SMS registration application.

```javascript theme={null}
<SMSOnboarding 
  /**
   * Optional function to fire after the application is submitted
   */
  onApplicationSubmit?: (data: SMSSetupBusinessFormData) => Promise<void>;
/>
```

<Note>
  If you would like to request any additional components, please reach out to us at [support@embedreach.com](mailto:support@embedreach.com).
</Note>

## Extra Merge Fields

The `ViewAutomationModal` component allows you to pass in a function to return extra merge fields for the automation.

```javascript theme={null}
getExtraMergeFields?: () => Promise<ReachMergeField[]>;
```

The expected return type is an array of `ReachMergeField` objects. Each merge field can be either a `static` or `dynamic` type.

Each merge field must have a unique `id` that will be used when updating merge field contents. The `type` field determines whether it's a static or dynamic merge field.

<Note>
  You **cannot** have two identical template names for **any** merge fields.
</Note>

<Note>
  When a merge field includes an `image` configuration, the image will be automatically added as an attachment to the message. The merge field still provides its text value for use in the message content, while the image serves as a supplementary attachment (e.g., a QR code for a coupon, a product image, etc.).
</Note>

### Dynamic Merge Field

```javascript theme={null}
type DynamicMergeField = {
  type: 'dynamic';
  id: string;
  mergeFields: {
    displayName: string;
    templateName: string;
    /**
     * Optional image configuration for this merge field. Auto-applied to SMS if the merge field text is used.
     */
    image?: {
      placeholderUrl: string; // URL for placeholder image to show in UI
      maxSize: number; // Max size in bytes for this image (used to deduct from total message size)
    };
  }[];
  url: string;  // e.g. "https://acme.co/id/" (we require https)
};
```

#### URL Requirements

The URL will be called with a `POST` request with the following body:

```javascript theme={null}
{
 userIds: string[];
 id: string; // `id` is the id of the dynamic merge field
 automationId: string; // `automationId` is the id of the automation
 tenantExternalId: string; // `tenantExternalId` is the external id of the business
}
```

And a the following headers:

```javascript theme={null}
{
  'Authorization': 'Bearer your-auth-token'
}
```

Where the `your-auth-token` is a signed JWT token using the shared secret for the platform.

The userIds are mapped to the `externalId` [Partner Resource](/api-reference/endpoint/get-api-resources-%7Bschemadefinitionnameorid%7D-%7Bexternalid%7D).

The response should be a JSON object with the following format:

```javascript theme={null}
{
 [userId: string]: {
  /**
   * The value of the merge field
   * For text fields: string
   * For fields with images: { value: string; image?: { url: string } }
   */
  [mergeFieldId: string]: string | { value: string; image?: { url: string } };
 }
}
```

This means for example if you have a dynamic merge field, you can pass up to 20 merge fields in a single request.

```javascript theme={null}
{
  type: 'dynamic',
  id: 'unique_id_for_merge_fields',
  mergeFields: [
    {
      displayName: 'Coupon Code',
      templateName: 'coupon_code'
    },
    {
      displayName: 'Expiration Date',
      templateName: 'expiration_date'
    },
    {
      displayName: 'Coupon With QR Code',
      templateName: 'coupon_with_qr_code',
      image: {
        placeholderUrl: 'https://acme.co/placeholder-qr-code.jpg',
        maxSize: 1600
      }
    },
    ... // other merge fields you might want to pass
  ],
  url: 'https://acme.co/id/'
}
```

The URL will be called with the following body:

```javascript theme={null}
{
  userIds: ['123', '456'],
  id: 'unique_id_for_merge_fields',
  tenantExternalId: 'acme' // the external id of the business
}
```

And the expected response would be where the key is the userId and it returns a dictionary of all the `templateNames` and their values:

```javascript theme={null}
{
  '123': {
    'coupon_code': '123456',
    'expiration_date': '2021-01-01',
    'coupon_with_qr_code': {
      value: '123456',
      image: {
        url: 'https://acme.co/qr-codes/123456.png'
      }
    }
  },
  '456': {
    'coupon_code': '456789',
    'expiration_date': '2021-02-01',
    'coupon_with_qr_code': {
      value: '456789',
      image: {
        url: 'https://acme.co/qr-codes/456789.png'
      }
    }
  }
}

```
