---
title: "แอ็กชันหลังการติดตั้งและการเริ่มต้นใช้งาน | Tajo"
description: "ตั้งค่าพฤติกรรมหลังการติดตั้งและสร้างขั้นตอน onboarding ที่มีประสิทธิภาพสำหรับ Stripe App ของคุณ"
url: https://tajo.io/th/docs/stripe-apps/post-install/
markdown: https://tajo.io/th/docs/stripe-apps/post-install.md
lang: th-TH
author: "Set Noa"
author_url: https://tajo.io/th/set-noa/
robots: noindex
---

ขอสิทธิ์ใช้งานล่วงหน้า

กรอกชื่อและที่อยู่อีเมลที่ทำงานของคุณ เราจะส่งลิงก์เพื่อยืนยันคำขอเข้าใช้งาน Tajo ทางอีเมล

# แอ็กชันหลังการติดตั้งและการเริ่มต้นใช้งาน

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

แอ็กชันหลังการติดตั้งเป็นตัวกำหนดว่าจะเกิดอะไรขึ้นทันทีหลังจากผู้ใช้ติดตั้ง Stripe App ของคุณ ประสบการณ์หลังการติดตั้งที่ออกแบบมาอย่างดีจะพาผู้ใช้ผ่านขั้นตอนการตั้งค่าและช่วยเพิ่มอัตราการเริ่มใช้งานจริง

Caution

**สถานะ: วางแผนไว้ ยังไม่ได้สร้าง** Tajo ไม่มี Stripe App จึงยังไม่มีสิ่งใดในส่วนนี้ที่ติดตั้งได้ในปัจจุบัน ตัวระบุแอป URL รวมถึงข้อมูลรับรองในหน้านี้เป็นตัวอย่างประกอบคำอธิบาย ไม่ใช่ปลายทางที่ใช้งานได้จริง

## ประเภทของแอ็กชันหลังการติดตั้ง

Stripe รองรับแอ็กชันหลังการติดตั้งสี่ประเภท โดยแต่ละประเภทตั้งค่าได้ใน manifest ของแอป:

### 1. ลิงก์ไปยังแอป (ค่าเริ่มต้น)

เปิดแอปใน drawer viewport ที่เป็นค่าเริ่มต้น นี่คือพฤติกรรมเริ่มต้นหากไม่ได้ระบุ `post_install_action`:

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

ผู้ใช้จะเห็น viewport `drawer.default` ของแอปในแถบด้านข้างของ Stripe Dashboard

### 2. ลิงก์ไปยังหน้า onboarding

เปิดมุมมอง onboarding เฉพาะของแอป เพื่อให้ประสบการณ์การตั้งค่าที่ไม่มีสิ่งรบกวน:

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

วิธีนี้ต้องประกาศ viewport `onboarding` ไว้ใน manifest ของคุณ:

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

### 3. ลิงก์ไปยังการตั้งค่า

เปิดมุมมองการตั้งค่าของแอป มีประโยชน์เมื่อแอปต้องใช้ API key หรือการตั้งค่าอื่นก่อนเริ่มใช้งาน:

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

วิธีนี้ต้องมี viewport `settings`:

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

### 4. ลิงก์ไปยัง URL ภายนอก

พาผู้ใช้ไปยัง URL ภายนอกเพื่อทำการตั้งค่า ใช้วิธีนี้เมื่อขั้นตอน onboarding ของคุณอยู่นอก Stripe Dashboard:

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

Caution

URL ภายนอกต้องใช้ HTTPS และควรระบุไว้ใน `allowed_redirect_uris` ของคุณ ทีมตรวจสอบของ Stripe จะยืนยันว่า URL ภายนอกนั้นให้ประสบการณ์การตั้งค่าที่ใช้งานได้จริง

## แนวทางปฏิบัติที่ดีสำหรับ onboarding

### ทำให้ใช้งานง่ายที่สุด

ลดจำนวนขั้นตอนที่ต้องทำก่อนเริ่มใช้งานให้เหลือน้อยที่สุด:

- **กรอกข้อมูลล่วงหน้า** จากข้อมูลที่มีอยู่ในบริบทของบัญชี Stripe
- **ใช้ค่าเริ่มต้นที่เหมาะสม** สำหรับตัวเลือกการตั้งค่าต่าง ๆ
- **อนุญาตให้ข้ามได้** ในขั้นตอนที่ไม่บังคับ พร้อมเส้นทางที่ชัดเจนสำหรับทำให้เสร็จภายหลัง
- **แสดงความคืบหน้า** ด้วยตัวบอกขั้นตอนสำหรับกระบวนการที่มีหลายขั้นตอน

### ให้ปรับแต่งได้

ให้ผู้ใช้ตั้งค่าการเชื่อมต่อได้ตามความต้องการของตนเอง:

- **ตัวเลือกการจับคู่ข้อมูล** ให้ผู้ใช้เลือกได้ว่าฟิลด์ใดของ Stripe จะซิงค์ไปยัง Brevo
- **ความถี่ในการซิงค์** เสนอตัวเลือกซิงค์รายชั่วโมงหรือรายวัน
- **การซิงค์แบบเลือกเฉพาะ** ให้ผู้ใช้เลือกได้ว่าจะซิงค์ลูกค้าหรือสินค้ารายการใด
- **การตั้งค่าการแจ้งเตือน** กำหนดการแจ้งเตือนสำหรับข้อผิดพลาดในการซิงค์หรือเหตุการณ์สำคัญ

### ทำให้เห็นคุณค่าที่ตรงจุด

แสดงคุณค่าให้เห็นทันที:

- **แสดงตัวอย่างข้อมูลที่จะซิงค์** ก่อนเปิดใช้งานการเชื่อมต่อ
- **บอกว่าจะเกิดอะไรขึ้น** เมื่อผู้ใช้ตั้งค่าเสร็จ
- **มีตัวเลือกทดลองซิงค์** เพื่อยืนยันว่าการเชื่อมต่อทำงานได้
- **แสดงตัวชี้วัดความสำเร็จ** หลังจากการซิงค์ครั้งแรกเสร็จสิ้น

## คอมโพเนนต์ OnboardingView

คอมโพเนนต์ `OnboardingView` จะแสดงผลในโมดัลแบบโฟกัสเมื่อผู้ใช้ติดตั้งแอป:

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

## ขั้นตอนการเข้าสู่ระบบด้วย SignInView

หากแอปของคุณกำหนดให้ผู้ใช้ต้องเข้าสู่ระบบด้วยบัญชีภายนอก เช่น Tajo ให้ใช้มุมมองการเข้าสู่ระบบแยกต่างหาก:

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

## เปิดด้วย deep link พร้อม query parameter

คุณสามารถเปิดขั้นตอน onboarding ที่ต้องการ หรือกรอกข้อมูลล่วงหน้าได้ด้วย query parameter ใน deep link:

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

สร้าง deep link ที่กรอกข้อมูล 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('');
```

## การรองรับผู้ใช้ที่กลับมาใช้งาน

เมื่อผู้ใช้เปิดแอปของคุณหลังจากทำ onboarding เสร็จแล้ว ให้ตรวจสอบสถานะของผู้ใช้และแสดงมุมมองที่เหมาะสม:

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

จัดเก็บสถานะการทำ onboarding เสร็จสิ้นไว้ใน Stripe Secret Store เพื่อให้ตรวจสอบผู้ใช้ที่กลับมาใช้งานได้โดยไม่ต้องเรียก API ภายนอก
