# UI/iFrame integrations

## iFrame integrations

You can develop your own integration that is injected into Missive with an iframe that can interact with our application via a JavaScript library.

### Library

Include this script in your integration page. Check out the [JavaScript API](https://missiveapp.com/docs/developers/ui-iframe-integrations/javascript-api).

```html
<script src="https://integrations.missiveapp.com/missive.js"></script>
```

### Styles

For your convenience, we also provide a stylesheet for you to include if you want your integration to match our styles. Not only does it accelerate development, it will also make your integration support all of our themes by default. Check out our [CSS styleguide](https://integrations.missiveapp.com/styleguide/).

```html
<link href="https://integrations.missiveapp.com/missive.css" rel="stylesheet">
```

### Development

`https` is required when adding a custom integration to Missive. During development, we suggest using a tool like [Caddy](https://caddyserver.com/) or [Ngrok](https://ngrok.com/) to create a secure tunnel to your local development server.

### iOS compatibility

iFrame integrations are supported on iOS. Missive on iOS is a web app loaded from `localhost`, which makes it stricter about iframe security headers.

If your integration loads on web and desktop but appears blank on iOS, check your `Content-Security-Policy` headers. Setting `frame-ancestors: *` will cause the iframe to fail on iOS. Remove the `frame-ancestors` directive entirely to allow loading from `localhost`.

### Debugging

To debug your integration, you need access to the browser console:

1. Open the Command Bar with <kbd>⌘/Ctrl</kbd> + <kbd>K</kbd>
2. Search for `OPEN_DEV_TOOLS`
3. Select the command to open the browser developer tools

This gives you access to the full browser console where you can:

* View console.log output from your integration
* Inspect errors and stack traces
* Debug JavaScript code
* Monitor network requests
* Inspect the DOM

## Security

There are multiple ways you can secure your iFrame:

{% stepper %}
{% step %}

#### Implement authentication inside the iFrame (most secure)

Implement authentication logic in your iFrame itself so your users have to log in before seeing the iFrame content.

You can use Missive's secure storage to persist authentication:

```javascript
// When user needs to authenticate
const token = await Missive.storeGet('auth_token')
if (!token) {
  // Show login form
  // After successful login:
  await Missive.storeSet('auth_token', 'user_token_12345')
} else {
  // Validate token and show content
}
```

* Values are stored per-integration and per-user
* Tokens persist across page reloads
* Storage is managed securely by Missive and cleared at user log out
  {% endstep %}

{% step %}

#### Pass a token in the integration URL parameters (easiest)

Pass a token in the integration URL parameters that your server will use to authenticate the request before serving the iFrame content.

Example URL entered in Missive: <https://acme.com/my-iframe?auth=12345abcde>
{% endstep %}

{% step %}

#### Delegate OAuth flow to Missive with initiateCallback (best for OAuth providers)

```javascript
async function authenticateWithOAuth() {
  try {
    // 1. Initiate OAuth flow
    const response = await Missive.initiateCallback('https://your-auth-endpoint')

    // 2. Response will contain query params from the OAuth redirect
    const { access_token } = response

    // 3. Store the token for future use
    await Missive.storeSet('oauth_token', access_token)
  } catch (error) {
    console.error('OAuth flow failed:', error)
  }
}
```

How it works:

* Missive opens the auth URL in a new browser tab
* Adds a `redirectTo` parameter to your URL
* After OAuth completion, redirect to the provided `redirectTo` URL with your tokens/data as query params
* The browser tab closes automatically
* Your integration receives the data in the `response` object

Important notes:

* Works around iframe OAuth limitations
* Compatible with iOS (uses localStorage instead of cookies)
* The `redirectTo` URL is unique per attempt
* Store the `redirectTo` URL during OAuth redirects

Remember:

* Always validate tokens on your server
* Use HTTPS for all communications
  {% endstep %}
  {% endstepper %}

## Need help building your integration?

If you don't have the technical skills to build a custom integration, check our [partners list](https://missiveapp.com/partners) for developers who can help.

## Need more specific answers?

[Contact us](https://missiveapp.com/docs/developers/contact)
