> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tagada.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Initialize Checkout with Items

> How to programmatically create a checkout session with line items

# Initialize Checkout Session with Items

Learn how to programmatically create a new checkout session with line items using the `init()` function from `useCheckout()`.

<Info>
  **Use Case:** This is useful when you want to create a checkout without a pre-existing `checkoutToken`, such as:

  * Landing pages that add products directly to checkout
  * BOGO funnels that start with a specific bundle
  * Custom product selectors that initialize checkout on-the-fly
</Info>

***

## Basic Example

```tsx theme={null}
import { useCheckout, useFunnel } from '@tagadapay/plugin-sdk/v2';
import { useEffect, useRef } from 'react';

export default function CheckoutPage() {
  const { checkout, init, error } = useCheckout({
    checkoutToken: '', // No token - we'll create one
  });
  
  const { context } = useFunnel();
  const hasInitialized = useRef(false);

  // Initialize checkout when component mounts
  useEffect(() => {
    if (!checkout && init && !hasInitialized.current && context) {
      hasInitialized.current = true;

      init({
        storeId: 'your-store-id',
        lineItems: [
          {
            variantId: 'variant_abc123',
            quantity: 1,
          },
        ],
      }).catch((err) => {
        console.error('Failed to initialize checkout:', err);
      });
    }
  }, [checkout, init, context]);

  if (!checkout) {
    return <div>Initializing checkout...</div>;
  }

  return (
    <div>
      <h1>Checkout</h1>
      <p>Total: ${(checkout.summary.total / 100).toFixed(2)}</p>
    </div>
  );
}
```

***

## Complete Example with Store ID

```tsx theme={null}
import { useCheckout, useFunnel, usePluginConfig } from '@tagadapay/plugin-sdk/v2';
import { useEffect, useRef, useState } from 'react';

export default function CheckoutPage() {
  const { storeId } = usePluginConfig();
  const { checkout, init, error } = useCheckout({
    checkoutToken: '',
  });
  const { context, isInitialized } = useFunnel();
  
  const hasInitialized = useRef(false);
  const [initError, setInitError] = useState<string | null>(null);

  useEffect(() => {
    // Wait for funnel to be ready
    if (!isInitialized || !context) return;
    
    // Only initialize once
    if (hasInitialized.current || checkout) return;
    
    // Check we have the init function
    if (!init) return;

    hasInitialized.current = true;
    
    init({
      storeId: storeId,
      lineItems: [
        {
          variantId: 'variant_xyz789', // Replace with your variant ID
          quantity: 1,
        },
      ],
    }).catch((err) => {
      console.error('❌ Failed to initialize checkout:', err);
      setInitError(err.message || 'Failed to create checkout');
    });
  }, [checkout, init, storeId, isInitialized, context]);

  // Show error state
  if (initError || error) {
    return (
      <div className="error">
        <h2>Unable to Initialize Checkout</h2>
        <p>{initError || error?.message}</p>
      </div>
    );
  }

  // Show loading state
  if (!checkout) {
    return (
      <div className="loading">
        <div className="spinner" />
        <p>Creating your checkout...</p>
      </div>
    );
  }

  // Checkout is ready!
  return (
    <div className="checkout">
      <h1>Checkout</h1>
      <div className="summary">
        <p>Items: {checkout.summary.items.length}</p>
        <p>Total: ${(checkout.summary.total / 100).toFixed(2)}</p>
      </div>
    </div>
  );
}
```

***

## With Static Resources (CRM-Configured Variants)

This example shows how to use variant IDs from funnel static resources:

```tsx theme={null}
import { useCheckout, useFunnel, usePluginConfig } from '@tagadapay/plugin-sdk/v2';
import { useEffect, useRef } from 'react';

export default function CheckoutPage() {
  const { storeId } = usePluginConfig();
  const { checkout, init } = useCheckout({ checkoutToken: '' });
  const { context, isInitialized } = useFunnel();
  
  const hasInitialized = useRef(false);

  // Get variant ID from static resources (configured in CRM)
  const variantId = context?.static?.variant?.id;

  useEffect(() => {
    // Wait for all dependencies
    if (!isInitialized || !context || !variantId) return;
    if (hasInitialized.current || checkout || !init) return;

    hasInitialized.current = true;
    console.log('🚀 Initializing checkout with variant:', variantId);

    init({
      storeId: storeId,
      lineItems: [
        {
          variantId: variantId,
          quantity: 1,
        },
      ],
    }).catch((err) => {
      console.error('❌ Init failed:', err);
    });
  }, [checkout, init, storeId, variantId, isInitialized, context]);

  if (!checkout) return <div>Loading...</div>;

  return <div>Checkout Ready!</div>;
}
```

<Tip>
  In your plugin manifest, declare static resources:

  ```json theme={null}
  {
    "features": [{
      "requirements": [{
        "resource": "variant",
        "from": [{ "name": "id", "type": "static" }]
      }]
    }]
  }
  ```

  Then merchants can configure which variant to use in the CRM Funnel Builder.
</Tip>

***

## Multiple Line Items

```tsx theme={null}
init({
  storeId: storeId,
  lineItems: [
    {
      variantId: 'variant_main',
      quantity: 2,
    },
    {
      variantId: 'variant_addon',
      quantity: 1,
    },
  ],
});
```

***

## With Specific Price ID (Subscription)

```tsx theme={null}
import { useProducts } from '@tagadapay/plugin-sdk/v2';

function CheckoutWithSubscription() {
  const { storeId } = usePluginConfig();
  const { checkout, init } = useCheckout({ checkoutToken: '' });
  const { getVariant } = useProducts({ 
    variantIds: ['variant_abc123'],
  });
  
  const hasInitialized = useRef(false);

  useEffect(() => {
    if (hasInitialized.current || checkout || !init) return;
    
    const variantData = getVariant('variant_abc123');
    if (!variantData) return;

    // Get subscription price (recurring: true)
    const subscriptionPrice = variantData.variant.prices?.find(
      (p: { recurring?: boolean }) => p.recurring === true
    );

    if (!subscriptionPrice) return;

    hasInitialized.current = true;

    init({
      storeId: storeId,
      lineItems: [
        {
          variantId: 'variant_abc123',
          priceId: subscriptionPrice.id, // Specific price for subscription
          quantity: 1,
        },
      ],
    });
  }, [checkout, init, storeId, getVariant]);

  return <div>...</div>;
}
```

***

## Key Points

<AccordionGroup>
  <Accordion title="When to use init()" icon="question">
    Use `init()` when:

    * ✅ No `checkoutToken` is provided in the URL
    * ✅ You want to programmatically create a checkout
    * ✅ Building a landing page that adds products to cart
    * ✅ Creating custom bundle selectors

    Don't use `init()` when:

    * ❌ You have a `checkoutToken` from the URL
    * ❌ The checkout already exists (checkout data loaded)
  </Accordion>

  <Accordion title="Preventing duplicate initialization" icon="shield">
    Always use a ref to prevent multiple init calls:

    ```tsx theme={null}
    const hasInitialized = useRef(false);

    useEffect(() => {
      if (hasInitialized.current) return;
      hasInitialized.current = true;
      
      init({ ... });
    }, []);
    ```
  </Accordion>

  <Accordion title="Wait for dependencies" icon="clock">
    Make sure to wait for:

    1. Funnel to be initialized (`isInitialized`)
    2. Context to be available (`context`)
    3. Static resources to load (if using them)

    ```tsx theme={null}
    if (!isInitialized || !context) return;
    if (!variantId) return; // if using static resources
    ```
  </Accordion>

  <Accordion title="Error handling" icon="triangle-exclamation">
    Always handle initialization errors:

    ```tsx theme={null}
    init({ ... }).catch((err) => {
      console.error('Init failed:', err);
      // Show error UI to user
    });
    ```
  </Accordion>
</AccordionGroup>

***

## API Reference

### init() Parameters

```typescript theme={null}
init({
  storeId: string;           // Required: Your store ID
  lineItems: Array<{
    variantId: string;       // Required: Product variant ID
    priceId?: string;        // Optional: Specific price ID (for subscriptions)
    quantity: number;        // Required: Quantity to add
  }>;
})
```

### Returns

```typescript theme={null}
Promise<void>  // Resolves when checkout is created
```

***

## Common Patterns

### Pattern 1: Auto-initialize with Default Product

```tsx theme={null}
// Perfect for landing pages with a single product
const variantId = 'variant_default_product';

useEffect(() => {
  if (!checkout && init && !hasInitialized.current) {
    hasInitialized.current = true;
    init({ storeId, lineItems: [{ variantId, quantity: 1 }] });
  }
}, [checkout, init, storeId]);
```

### Pattern 2: Initialize from Static Resources

```tsx theme={null}
// Perfect for funnels where merchant configures products
const variantId = context?.static?.variant?.id;

useEffect(() => {
  if (variantId && !checkout && init && !hasInitialized.current) {
    hasInitialized.current = true;
    init({ storeId, lineItems: [{ variantId, quantity: 1 }] });
  }
}, [variantId, checkout, init, storeId]);
```

### Pattern 3: Initialize with User Selection

```tsx theme={null}
// Perfect for bundle selectors or product pickers
const [selectedVariant, setSelectedVariant] = useState<string | null>(null);

const handleSelectVariant = async (variantId: string) => {
  setSelectedVariant(variantId);
  
  await init({
    storeId,
    lineItems: [{ variantId, quantity: 1 }],
  });
};
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Update Line Items" icon="pen" href="/developer-tools/sdk/api#usecheckout">
    Learn how to update items after initialization
  </Card>

  <Card title="Process Payment" icon="credit-card" href="/developer-tools/sdk/api#payment-hooks">
    Process payment after checkout is ready
  </Card>

  <Card title="Static Resources" icon="database" href="/developer-tools/sdk/funnel-resources">
    Use CRM-configured resources
  </Card>

  <Card title="Complete Example" icon="code" href="/developer-tools/sdk/examples">
    See full checkout implementations
  </Card>
</CardGroup>
