Beantrage frühzeitigen Zugang

Gib deinen Vornamen und eine E-Mail-Adresse oder Telefonnummer an. Wir melden uns mit den Details zum Tajo-Zugang bei dir.

Post-Install-Aktionen & Onboarding

Post-Install-Aktionen bestimmen, was unmittelbar nach der Installation deiner Stripe App passiert. Ein gut gestalteter Ablauf nach der Installation führt Nutzer:innen durch die Einrichtung und erhöht die Aktivierungsrate.

Typen von Post-Install-Aktionen

Stripe unterstützt vier Typen von Post-Install-Aktionen, die du jeweils im Manifest deiner App konfigurierst:

Öffnet die App im Standard-Drawer-Viewport. Das ist das Standardverhalten, wenn du kein post_install_action angibst:

{
"post_install_action": {
"type": "default"
}
}

Nutzer:innen sehen dann den Viewport drawer.default deiner App in der Seitenleiste des Stripe Dashboards.

Öffnet die eigene Onboarding-Ansicht der App und schafft so eine fokussierte Einrichtung:

{
"post_install_action": {
"type": "onboarding"
}
}

Dafür muss im Manifest ein Viewport onboarding deklariert sein:

{
"ui_extension": {
"views": [
{
"viewport": "stripe.dashboard.onboarding",
"component": "OnboardingView"
}
]
},
"post_install_action": {
"type": "onboarding"
}
}

Öffnet die Einstellungsansicht der App. Das ist sinnvoll, wenn die App vor der Nutzung API-Schlüssel oder eine Konfiguration braucht:

{
"post_install_action": {
"type": "settings"
}
}

Dafür muss ein Viewport settings vorhanden sein:

{
"ui_extension": {
"views": [
{
"viewport": "stripe.dashboard.settings",
"component": "SettingsView"
}
]
},
"post_install_action": {
"type": "settings"
}
}

Leitet Nutzer:innen zur Einrichtung auf eine externe URL weiter. Nutze das, wenn dein Onboarding außerhalb des Stripe Dashboards liegt:

{
"post_install_action": {
"type": "external",
"url": "https://app.tajo.io/stripe/setup"
}
}

Caution

Externe URLs müssen HTTPS verwenden und sollten in deinen allowed_redirect_uris stehen. Das Review-Team von Stripe prüft, ob die externe URL eine funktionierende Einrichtung bietet.

Bewährte Vorgehensweisen für das Onboarding

Mach es mühelos

Halte die Zahl der Schritte bis zum Start so klein wie möglich:

  • Fülle Angaben vor, die aus dem Kontext des Stripe-Kontos verfügbar sind
  • Setze sinnvolle Standardwerte für Konfigurationsoptionen
  • Erlaube das Überspringen optionaler Schritte und zeige klar, wie man sie später nachholt
  • Zeige den Fortschritt bei mehrstufigen Abläufen mit Schrittanzeigen

Mach es anpassbar

Lass Nutzer:innen die Integration auf ihren Bedarf zuschneiden:

  • Optionen für die Datenzuordnung, damit sie wählen können, welche Stripe-Felder nach Brevo synchronisiert werden
  • Sync-Frequenz, biete Synchronisierung in Echtzeit, stündlich oder täglich an
  • Selektive Synchronisierung, damit sie wählen können, welche Kundschaft oder Produkte synchronisiert werden
  • Benachrichtigungseinstellungen, damit sie Warnungen zu Sync-Fehlern oder wichtigen Ereignissen konfigurieren können

Mach es relevant

Zeige den Nutzen sofort:

  • Zeige eine Vorschau der synchronisierten Daten, bevor die Integration aktiviert wird
  • Zeige, was passiert, sobald die Einrichtung abgeschlossen ist
  • Biete einen Test-Sync an, mit dem sich die Verbindung überprüfen lässt
  • Zeige Erfolgskennzahlen, sobald die erste Synchronisierung durch ist

Komponente OnboardingView

Die Komponente OnboardingView wird in einem fokussierten Modal gerendert, sobald die App installiert wird:

import {
Box,
Button,
Inline,
Icon,
Banner,
TextField,
Select,
Divider,
} from '@stripe/ui-extension-sdk/ui';
import type { ExtensionContextValue } from '@stripe/ui-extension-sdk/context';
import { useState } from 'react';
const OnboardingView = ({ environment, userContext }: ExtensionContextValue) => {
const [step, setStep] = useState(1);
const [brevoApiKey, setBrevoApiKey] = useState('');
const [syncMode, setSyncMode] = useState('realtime');
const [isConnecting, setIsConnecting] = useState(false);
const [error, setError] = useState<string | null>(null);
const totalSteps = 3;
const handleConnect = async () => {
setIsConnecting(true);
setError(null);
try {
// Store the API key securely
await storeBrevoApiKey(brevoApiKey);
// Verify the connection
const result = await verifyBrevoConnection(brevoApiKey);
if (result.success) {
setStep(2);
} else {
setError('Unable to connect to Brevo. Please check your API key.');
}
} catch (err) {
setError('Connection failed. Please try again.');
} finally {
setIsConnecting(false);
}
};
return (
<Box css={{ padding: 'large' }}>
{/* Progress indicator */}
<Inline css={{ marginBottom: 'large' }}>
Step {step} of {totalSteps}
</Inline>
{error && (
<Banner type="critical" title="Connection Error">
{error}
</Banner>
)}
{step === 1 && (
<Box>
<Inline css={{ fontWeight: 'bold', fontSize: 'large' }}>
Connect Your Brevo Account
</Inline>
<Inline css={{ marginTop: 'small', color: 'secondary' }}>
Enter your Brevo API key to start syncing customer data.
</Inline>
<TextField
label="Brevo API Key"
placeholder="xkeysib-..."
value={brevoApiKey}
onChange={(e) => setBrevoApiKey(e.target.value)}
css={{ marginTop: 'medium' }}
/>
<Inline css={{ marginTop: 'xsmall', color: 'secondary', fontSize: 'small' }}>
Find your API key in Brevo under Settings &gt; SMTP &amp; API &gt; API Keys
</Inline>
<Button
type="primary"
onPress={handleConnect}
disabled={!brevoApiKey || isConnecting}
css={{ marginTop: 'medium' }}
>
{isConnecting ? 'Connecting...' : 'Connect Brevo'}
</Button>
</Box>
)}
{step === 2 && (
<Box>
<Inline css={{ fontWeight: 'bold', fontSize: 'large' }}>
Configure Sync Settings
</Inline>
<Select
label="Sync Mode"
value={syncMode}
onChange={(value) => setSyncMode(value)}
css={{ marginTop: 'medium' }}
>
<option value="realtime">Real-time (recommended)</option>
<option value="hourly">Every hour</option>
<option value="daily">Once per day</option>
</Select>
<Divider css={{ marginY: 'medium' }} />
<Button type="primary" onPress={() => setStep(3)}>
Continue
</Button>
<Button type="secondary" onPress={() => setStep(1)}>
Back
</Button>
</Box>
)}
{step === 3 && (
<Box>
<Banner type="default" title="Ready to Sync">
Your Brevo account is connected. Tajo will begin syncing
customer data automatically.
</Banner>
<Box css={{ marginTop: 'medium' }}>
<Inline css={{ fontWeight: 'bold' }}>What happens next:</Inline>
<ul>
<li>Existing Stripe customers will sync to Brevo contacts</li>
<li>New customers and events will sync in real-time</li>
<li>View sync status on any customer's detail page</li>
</ul>
</Box>
<Button type="primary" onPress={() => {/* Navigate to dashboard */}}>
Go to Dashboard
</Button>
</Box>
)}
</Box>
);
};
export default OnboardingView;

Anmeldeablauf mit SignInView

Wenn sich Nutzer:innen für deine App bei einem externen Konto anmelden müssen, etwa bei Tajo, nutze eine eigene Anmeldeansicht:

import {
Box,
Button,
Inline,
TextField,
Banner,
Link,
} from '@stripe/ui-extension-sdk/ui';
import { useState } from 'react';
const SignInView = ({ onSignInComplete }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSignIn = async () => {
setIsLoading(true);
setError(null);
try {
const response = await fetch('https://api.tajo.io/v1/auth/stripe-app', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
throw new Error('Invalid credentials');
}
const { token } = await response.json();
// Store the auth token securely in Stripe's Secret Store
await storeAuthToken(token);
onSignInComplete();
} catch (err) {
setError('Sign-in failed. Please check your credentials and try again.');
} finally {
setIsLoading(false);
}
};
return (
<Box css={{ padding: 'large' }}>
<Inline css={{ fontWeight: 'bold', fontSize: 'large' }}>
Sign in to Tajo
</Inline>
<Inline css={{ marginTop: 'small', color: 'secondary' }}>
Connect your Tajo account to enable Brevo sync.
</Inline>
{error && (
<Banner type="critical" title="Sign-in Failed">
{error}
</Banner>
)}
<TextField
label="Email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
css={{ marginTop: 'medium' }}
/>
<TextField
label="Password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
css={{ marginTop: 'small' }}
/>
<Button
type="primary"
onPress={handleSignIn}
disabled={!email || !password || isLoading}
css={{ marginTop: 'medium' }}
>
{isLoading ? 'Signing in...' : 'Sign In'}
</Button>
<Link href="https://app.tajo.io/signup" external css={{ marginTop: 'small' }}>
Don't have a Tajo account? Sign up
</Link>
</Box>
);
};

Mit Query-Parametern in Deep Links startest du bestimmte Onboarding-Schritte oder füllst Daten vor:

import type { ExtensionContextValue } from '@stripe/ui-extension-sdk/context';
const OnboardingView = ({ environment }: ExtensionContextValue) => {
// Access query parameters from the deep link
const { queryParams } = environment;
// Pre-fill step from query parameter
const initialStep = queryParams?.step ? parseInt(queryParams.step) : 1;
// Pre-fill API key from query parameter (e.g., from Tajo dashboard)
const prefilledApiKey = queryParams?.brevo_key || '';
// Source tracking for analytics
const installSource = queryParams?.source || 'marketplace';
const [step, setStep] = useState(initialStep);
const [brevoApiKey, setBrevoApiKey] = useState(prefilledApiKey);
// ... rest of onboarding logic
};

So erzeugst du Deep Links, die Onboarding-Daten vorbefüllen:

// From your Tajo dashboard, generate a link that pre-fills the Brevo API key
const onboardingLink = [
'https://dashboard.stripe.com/live/acct_xxxxx/dashboard',
'?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.onboarding',
'&apps[com.tajo.brevo-integration][queryParams][step]=1',
'&apps[com.tajo.brevo-integration][queryParams][source]=tajo_dashboard',
].join('');

Wiederkehrende Nutzer:innen behandeln

Wenn jemand deine App nach abgeschlossenem Onboarding wieder öffnet, erkenne den Zustand und zeige die passende Ansicht:

const MainView = ({ environment, userContext }: ExtensionContextValue) => {
const [authState, setAuthState] = useState<'loading' | 'signed-out' | 'onboarding' | 'ready'>('loading');
useEffect(() => {
checkUserState().then((state) => {
setAuthState(state);
});
}, []);
switch (authState) {
case 'loading':
return <Spinner label="Loading..." />;
case 'signed-out':
return <SignInView onSignInComplete={() => setAuthState('onboarding')} />;
case 'onboarding':
return <OnboardingView onComplete={() => setAuthState('ready')} />;
case 'ready':
return <DashboardView />;
}
};

Tip

Speichere den Abschlussstatus des Onboardings im Stripe Secret Store. So erkennst du wiederkehrende Nutzer:innen ohne einen externen API-Aufruf.

Beantrage frühzeitigen Zugang

Gib deinen Vornamen und eine E-Mail-Adresse oder Telefonnummer an. Wir melden uns mit den Details zum Tajo-Zugang bei dir.

automatische Erkennung
AI-Assistent

Hallo! Fragen Sie mich alles über die Dokumentation.