Embedded Stripe Apps

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.

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:

AppCategoryUse Case
QuickBooksAccountingSync payments and invoices to QuickBooks
XeroAccountingAutomated bookkeeping and reconciliation
MailchimpMarketingSync customer data for email campaigns
Custom AppsAnyYour 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

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

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

// 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

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

// 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

import {
ConnectAppViewport,
ConnectComponentsProvider,
} from '@stripe/react-connect-js';
const BrevoCusomerView = ({ 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:

{
"metadata": {
"customer_id": "cus_platform_customer_id",
"customer_email": "[email protected]",
"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"
}
}
FieldTypeDescription
customer_idstringPlatform’s customer identifier
customer_emailstringCustomer email for invoice/receipt matching
product_namestringProduct display name for line items
product_idstringStripe product ID
quantitystringItem quantity
unit_amountstringUnit price in smallest currency unit (cents)
currencystringThree-letter ISO currency code
platform_feestringApplication fee amount in smallest currency unit
platform_fee_currencystringCurrency for the platform fee
tax_amountstringTax amount in smallest currency unit
tax_rate_idstringStripe tax rate ID applied
invoice_idstringAssociated invoice ID
order_idstringPlatform’s internal order identifier

Marketing Integrations

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

{
"metadata": {
"customer_id": "cus_xxxxx",
"customer_email": "[email protected]",
"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:

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.

AI Assistant

Hi! Ask me anything about the docs.

Start Free with Brevo