Acties na installatie en onboarding
Acties na installatie bepalen wat er direct gebeurt nadat een gebruiker je Stripe App installeert. Een goed ontworpen ervaring na de installatie leidt gebruikers door het instellen heen en verhoogt het activatiepercentage.
Soorten acties na installatie
Stripe ondersteunt vier soorten acties na installatie, die je allemaal in je app-manifest configureert:
1. Link naar de app (standaard)
Opent de app in de standaard drawer-viewport. Dit is het standaardgedrag als er geen post_install_action is opgegeven:
{ "post_install_action": { "type": "default" }}De gebruiker ziet de viewport drawer.default van de app in de zijbalk van het Stripe Dashboard.
2. Link naar de onboarding
Opent de speciale onboardingweergave van de app en biedt zo een gerichte installatie-ervaring:
{ "post_install_action": { "type": "onboarding" }}Hiervoor moet je in je manifest een onboarding-viewport declareren:
{ "ui_extension": { "views": [ { "viewport": "stripe.dashboard.onboarding", "component": "OnboardingView" } ] }, "post_install_action": { "type": "onboarding" }}3. Link naar de instellingen
Opent de instellingenweergave van de app, handig als de app API-sleutels of configuratie nodig heeft voordat je hem kunt gebruiken:
{ "post_install_action": { "type": "settings" }}Hiervoor is een settings-viewport nodig:
{ "ui_extension": { "views": [ { "viewport": "stripe.dashboard.settings", "component": "SettingsView" } ] }, "post_install_action": { "type": "settings" }}4. Link naar een externe URL
Stuurt de gebruiker door naar een externe URL om alles in te stellen. Gebruik dit als je onboardingflow buiten het Stripe Dashboard draait:
{ "post_install_action": { "type": "external", "url": "https://app.tajo.io/stripe/setup" }}Caution
Externe URL’s moeten HTTPS gebruiken en horen in je allowed_redirect_uris te staan. Het reviewteam van Stripe controleert of de externe URL een werkende installatie-ervaring biedt.
Best practices voor onboarding
Maak het moeiteloos
Beperk het aantal stappen dat nodig is om te starten:
- Vul informatie vooraf in die beschikbaar is vanuit de context van het Stripe-account
- Gebruik verstandige standaardwaarden voor configuratieopties
- Laat optionele stappen overslaan, met een duidelijke route om ze later alsnog af te ronden
- Toon de voortgang met stapindicatoren bij flows met meerdere stappen
Maak het aanpasbaar
Laat gebruikers de integratie naar hun eigen behoeften instellen:
- Opties voor datamapping, laat gebruikers kiezen welke Stripe-velden naar Brevo synchroniseren
- Synchronisatiefrequentie, bied synchronisatie in realtime, per uur of per dag aan
- Selectieve synchronisatie, laat gebruikers kiezen welke klanten of producten ze synchroniseren
- Notificatievoorkeuren, stel meldingen in voor synchronisatiefouten of belangrijke events
Maak het relevant
Laat direct waarde zien:
- Toon een voorbeeld van de gesynchroniseerde gegevens voordat de integratie wordt ingeschakeld
- Laat zien wat er gebeurt wanneer de gebruiker het instellen afrondt
- Bied een testsynchronisatie aan om te controleren of de verbinding werkt
- Toon succescijfers nadat de eerste synchronisatie is afgerond
De OnboardingView-component
De component OnboardingView verschijnt in een gerichte modal zodra de gebruiker de app installeert:
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 > SMTP & API > 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;Inlogflow met SignInView
Als gebruikers in je app moeten inloggen op een extern account, zoals Tajo, gebruik dan een aparte inlogweergave:
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> );};Deeplinks starten met queryparameters
Met queryparameters in deeplinks start je specifieke onboardingstappen of vul je gegevens vooraf in:
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};Genereer deeplinks die onboardinggegevens vooraf invullen:
// From your Tajo dashboard, generate a link that pre-fills the Brevo API keyconst 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('');Terugkerende gebruikers afhandelen
Wanneer een gebruiker je app opent nadat de onboarding is afgerond, bepaal je de status en toon je de juiste weergave:
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
Sla de afrondingsstatus van de onboarding op in de Stripe Secret Store, zodat je terugkerende gebruikers herkent zonder een externe API-aanroep.