---
title: "Acciones post-instalación y onboarding | Tajo"
description: "Configura el comportamiento posterior a la instalación y crea flujos de onboarding eficaces para tu Stripe App"
url: https://tajo.io/es/docs/stripe-apps/post-install/
markdown: https://tajo.io/es/docs/stripe-apps/post-install.md
lang: es-ES
author: "Set Noa"
author_url: https://tajo.io/es/set-noa/
robots: noindex
---

Solicita acceso anticipado

Escribe tu nombre y dirección de correo de trabajo. Te enviaremos un enlace para confirmar tu solicitud de acceso a Tajo.

# Acciones post-instalación y onboarding

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

Las acciones post-instalación determinan qué ocurre justo después de que alguien instala tu Stripe App. Una buena experiencia posterior a la instalación guía al usuario durante la configuración y aumenta las tasas de activación.

Caution

**Estado: planificada, no construida.** Tajo no tiene ninguna Stripe App, así que hoy no se puede instalar nada de esta sección. Los identificadores de app, las URLs y las credenciales de esta página son marcadores de posición ilustrativos, no endpoints reales.

## Tipos de acción post-instalación

Stripe admite cuatro tipos de acción post-instalación, y todos se configuran en el manifiesto de tu app:

### 1. Enlace a la app (predeterminado)

Abre la app en el viewport drawer predeterminado. Es el comportamiento por defecto si no indicas ninguna `post_install_action`:

```json
{
  "post_install_action": {
    "type": "default"
  }
}
```

El usuario ve el viewport `drawer.default` de la app en la barra lateral del Stripe Dashboard.

### 2. Enlace al onboarding

Abre la vista de onboarding específica de la app y ofrece así una experiencia de configuración enfocada:

```json
{
  "post_install_action": {
    "type": "onboarding"
  }
}
```

Esto exige declarar un viewport `onboarding` en tu manifiesto:

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

### 3. Enlace a los ajustes

Abre la vista de ajustes de la app. Resulta útil cuando la app necesita claves de API o alguna configuración antes de poder usarse:

```json
{
  "post_install_action": {
    "type": "settings"
  }
}
```

Esto exige un viewport `settings`:

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

### 4. Enlace a una URL externa

Redirige al usuario a una URL externa para la configuración. Úsalo cuando tu flujo de onboarding viva fuera del Stripe Dashboard:

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

Caution

Las URL externas deben usar HTTPS y deberían figurar en tus `allowed_redirect_uris`. El equipo de revisión de Stripe comprobará que la URL externa ofrece una experiencia de configuración funcional.

## Buenas prácticas de onboarding

### Hazlo fácil

Reduce al mínimo los pasos necesarios para empezar:

- **Rellena de antemano la información** que ya tienes del contexto de la cuenta de Stripe
- **Usa valores predeterminados sensatos** en las opciones de configuración
- **Permite omitir** los pasos opcionales, con un camino claro para completarlos más tarde
- **Muestra el progreso** con indicadores de paso en los flujos de varios pasos

### Hazlo personalizable

Deja que cada usuario adapte la integración a sus necesidades:

- **Opciones de mapeo de datos**, para que elijan qué campos de Stripe se sincronizan con Brevo
- **Frecuencia de sincronización**, ofrece opciones cada hora o una vez al día
- **Sincronización selectiva**, para que elijan qué clientes o productos se sincronizan
- **Preferencias de notificación**, para configurar avisos de errores de sincronización o de eventos importantes

### Hazlo relevante

Demuestra el valor desde el primer momento:

- **Muestra una vista previa de los datos sincronizados** antes de activar la integración
- **Explica qué va a pasar** cuando la persona termine la configuración
- **Ofrece una sincronización de prueba** para comprobar que la conexión funciona
- **Muestra métricas de éxito** cuando termine la primera sincronización

## Componente OnboardingView

El componente `OnboardingView` se renderiza en una modal enfocada cuando el usuario instala la app:

```typescript
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('hourly');
  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="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 will sync on the schedule you chose</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;
```

## Flujo de inicio de sesión con SignInView

Si tu app exige que el usuario inicie sesión en una cuenta externa (como la de Tajo), usa una vista de inicio de sesión específica:

```typescript
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.example.com/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>
  );
};
```

## Abrir un deep link con parámetros de consulta

Puedes abrir pasos concretos del onboarding o rellenar datos de antemano usando parámetros de consulta en los deep links:

```typescript
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
};
```

Genera deep links que rellenen de antemano los datos del onboarding:

```javascript
// 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('');
```

## Gestionar a los usuarios que vuelven

Cuando alguien abre tu app después de haber completado el onboarding, detecta su estado y muéstrale la vista adecuada:

```typescript
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

Guarda el estado de finalización del onboarding en el Secret Store de Stripe, así podrás detectar a los usuarios que vuelven sin hacer ninguna llamada a una API externa.
