---
title: "Embedded Stripe Apps | Tajo"
description: "Use Connect embedded components to integrate Stripe Apps into your own platform"
url: https://tajo.io/docs/stripe-apps/embedded-apps/
markdown: https://tajo.io/docs/stripe-apps/embedded-apps.md
lang: en-US
author: "Set Noa"
author_url: https://tajo.io/set-noa/
---

# Embedded Stripe Apps

[Set Noa](https://tajo.io/set-noa/)

Embedded Stripe Apps allow platforms built on Stripe Connect to surface third-party app functionality directly within their own dashboards. Using Connect embedded components, you can give your connected accounts access to apps like QuickBooks, Xero, and Mailchimp without them needing to visit the Stripe Dashboard.

Caution

**Status: planned, not built.** Tajo has no Stripe App, so nothing in this section can be installed today. The app identifiers, URLs and credentials on this page are illustrative placeholders, not live endpoints.

## Overview

Embedded apps use two key Connect embedded components:

- **`app-install`**: Renders an install button for a Stripe App within your platform UI
- **`app-viewport`**: Renders a specific app viewport within your platform UI

This enables platform operators to embed accounting, marketing, and operational tools directly in their product.

## Supported Apps

The following apps support embedding via Connect components:

| App | Category | Use Case |
| --- | --- | --- |
| **QuickBooks** | Accounting | Sync payments and invoices to QuickBooks |
| **Xero** | Accounting | Automated bookkeeping and reconciliation |
| **Mailchimp** | Marketing | Sync customer data for email campaigns |
| **Custom Apps** | Any | Your own Stripe Apps built for your platform |

Tip

The Tajo Brevo integration can be embedded in Connect platforms, allowing connected accounts to sync their Stripe data to Brevo through the platform’s own interface.

## Setup with Account Sessions API

To embed apps, you need to create Account Sessions with the appropriate components enabled:

### Server-Side: Create Account Session

```javascript
const stripe = require('stripe')('sk_live_...');

// Create an Account Session for the connected account
const accountSession = await stripe.accountSessions.create({
  account: 'acct_connected_account_id',
  components: {
    // Enable app install component
    app_install: {
      enabled: true,
      features: {
        allowed_apps: [
          'com.tajo.brevo-integration',
          'com.quickbooks.stripe-app'
        ],
      },
    },
    // Enable app viewport component
    app_viewport: {
      enabled: true,
      features: {
        allowed_apps: [
          'com.tajo.brevo-integration'
        ],
      },
    },
  },
});

// Return the client secret to your frontend
res.json({ clientSecret: accountSession.client_secret });
```

### Client-Side: Initialize Connect.js

```javascript
import { loadConnectAndInitialize } from '@stripe/connect-js';

// Initialize Connect.js with the account session
const stripeConnect = loadConnectAndInitialize({
  publishableKey: 'pk_live_...',
  fetchClientSecret: async () => {
    const response = await fetch('/api/account-session', {
      method: 'POST',
    });
    const { clientSecret } = await response.json();
    return clientSecret;
  },
});
```

## App Install Component

The `app-install` component renders an install button that connected accounts can use to install a Stripe App:

### JavaScript

```javascript
// Create the app install element
const appInstall = stripeConnect.create('app-install');

// Set the app to install
appInstall.setApp('com.tajo.brevo-integration');

// Mount to a DOM element
const container = document.getElementById('app-install-container');
appInstall.mount(container);

// Listen for install events
appInstall.on('app_installed', (event) => {
  console.log('App installed:', event.app_id);
  // Show the app viewport after installation
  showAppViewport();
});

appInstall.on('app_uninstalled', (event) => {
  console.log('App uninstalled:', event.app_id);
});
```

### React

```tsx
import {
  ConnectAppInstall,
  ConnectComponentsProvider,
} from '@stripe/react-connect-js';

const AppInstallButton = () => {
  return (
    <ConnectComponentsProvider connectInstance={stripeConnect}>
      <ConnectAppInstall
        app="com.tajo.brevo-integration"
        onAppInstalled={(event) => {
          console.log('App installed:', event.app_id);
        }}
        onAppUninstalled={(event) => {
          console.log('App uninstalled:', event.app_id);
        }}
      />
    </ConnectComponentsProvider>
  );
};
```

## App Viewport Component

The `app-viewport` component renders a specific app viewport within your platform:

### JavaScript

```javascript
// Create the app viewport element
const appViewport = stripeConnect.create('app-viewport');

// Configure the viewport
appViewport.setApp('com.tajo.brevo-integration');
appViewport.setViewport('stripe.dashboard.customer.detail');

// Pass object context (e.g., customer ID)
appViewport.setObjectContext({
  id: 'cus_xxxxx',
  object: 'customer',
});

// Mount to a DOM element
const container = document.getElementById('app-viewport-container');
appViewport.mount(container);
```

### React

```tsx
import {
  ConnectAppViewport,
  ConnectComponentsProvider,
} from '@stripe/react-connect-js';

const BrevoCustomerView = ({ customerId }: { customerId: string }) => {
  return (
    <ConnectComponentsProvider connectInstance={stripeConnect}>
      <ConnectAppViewport
        app="com.tajo.brevo-integration"
        viewport="stripe.dashboard.customer.detail"
        objectContext={{
          id: customerId,
          object: 'customer',
        }}
      />
    </ConnectComponentsProvider>
  );
};
```

## Destination Charge Metadata Schema

When using embedded apps with destination charges (common in Connect platforms), the charge metadata carries structured data that accounting and marketing integrations can consume.

### Accounting Integrations

For apps like QuickBooks and Xero, destination charge metadata follows this schema:

```json
{
  "metadata": {
    "customer_id": "cus_platform_customer_id",
    "customer_email": "customer@example.com",
    "product_name": "Premium Subscription",
    "product_id": "prod_xxxxx",
    "quantity": "1",
    "unit_amount": "4999",
    "currency": "usd",
    "platform_fee": "500",
    "platform_fee_currency": "usd",
    "tax_amount": "450",
    "tax_rate_id": "txr_xxxxx",
    "invoice_id": "inv_xxxxx",
    "order_id": "order_12345"
  }
}
```

| Field | Type | Description |
| --- | --- | --- |
| `customer_id` | string | Platform’s customer identifier |
| `customer_email` | string | Customer email for invoice/receipt matching |
| `product_name` | string | Product display name for line items |
| `product_id` | string | Stripe product ID |
| `quantity` | string | Item quantity |
| `unit_amount` | string | Unit price in smallest currency unit (cents) |
| `currency` | string | Three-letter ISO currency code |
| `platform_fee` | string | Application fee amount in smallest currency unit |
| `platform_fee_currency` | string | Currency for the platform fee |
| `tax_amount` | string | Tax amount in smallest currency unit |
| `tax_rate_id` | string | Stripe tax rate ID applied |
| `invoice_id` | string | Associated invoice ID |
| `order_id` | string | Platform’s internal order identifier |

### Marketing Integrations

For apps like Mailchimp and the Tajo Brevo integration, the metadata enables customer segmentation and campaign targeting:

```json
{
  "metadata": {
    "customer_id": "cus_xxxxx",
    "customer_email": "customer@example.com",
    "customer_name": "Jane Smith",
    "product_category": "subscription",
    "product_name": "Pro Plan",
    "purchase_value": "4999",
    "currency": "usd",
    "is_first_purchase": "true",
    "referral_source": "partner_campaign",
    "subscription_interval": "monthly",
    "lifetime_value": "29994"
  }
}
```

This metadata enables Brevo automations such as:

- **Welcome series** for first-time buyers (`is_first_purchase: "true"`)
- **Upsell campaigns** based on `product_category` and `purchase_value`
- **Retention flows** for subscription customers based on `subscription_interval`
- **Win-back campaigns** targeting high `lifetime_value` customers who churn

## Platform Integration Example

A complete platform integration embedding the Tajo Brevo app:

```tsx
import { useState, useEffect } from 'react';
import {
  ConnectAppInstall,
  ConnectAppViewport,
  ConnectComponentsProvider,
} from '@stripe/react-connect-js';
import { loadConnectAndInitialize } from '@stripe/connect-js';

const TajoBrevoPlatformIntegration = ({ connectedAccountId, customerId }) => {
  const [stripeConnect, setStripeConnect] = useState(null);
  const [isInstalled, setIsInstalled] = useState(false);

  useEffect(() => {
    const instance = loadConnectAndInitialize({
      publishableKey: 'pk_live_...',
      fetchClientSecret: async () => {
        const res = await fetch('/api/account-session', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ accountId: connectedAccountId }),
        });
        const { clientSecret } = await res.json();
        return clientSecret;
      },
    });
    setStripeConnect(instance);
  }, [connectedAccountId]);

  if (!stripeConnect) return <div>Loading...</div>;

  return (
    <ConnectComponentsProvider connectInstance={stripeConnect}>
      {!isInstalled ? (
        <div>
          <h3>Connect Brevo via Tajo</h3>
          <p>Install the Tajo integration to sync customer data with Brevo.</p>
          <ConnectAppInstall
            app="com.tajo.brevo-integration"
            onAppInstalled={() => setIsInstalled(true)}
          />
        </div>
      ) : (
        <div>
          <h3>Brevo Customer Profile</h3>
          <ConnectAppViewport
            app="com.tajo.brevo-integration"
            viewport="stripe.dashboard.customer.detail"
            objectContext={{
              id: customerId,
              object: 'customer',
            }}
          />
        </div>
      )}
    </ConnectComponentsProvider>
  );
};
```

## Security Considerations

When embedding apps in your platform:

- **Account Sessions expire**: Create new sessions as needed; do not cache client secrets
- **Scope control**: Use `allowed_apps` to restrict which apps can be installed
- **Data isolation**: Each connected account’s data is isolated; the platform cannot access app data
- **CSP headers**: Ensure your platform’s Content Security Policy allows connections to `https://connect-js.stripe.com`

Caution

Embedded app components require a Connect integration with Account Sessions API access. Standard Stripe accounts cannot use embedded components.
