# Checkout Component

The Checkout component provides a complete purchase flow including customer information collection, payment processing, and order confirmation.

## Overview

The Checkout component handles:
- Customer information (email, phone, address)
- Gift recipient details (optional)
- Payment processing (Stripe integration)
- Billing address
- Promo codes and gift cards
- Order summary and totals
- Marketing preferences
- Tip options
- Order confirmation

## Basic Usage

### Checkout Drawer (Default)

The checkout drawer opens automatically when users click "Checkout" from the cart. No additional setup required.

### Hosted Checkout Page

For a full-page checkout experience, inject checkout into a dedicated container:

```javascript
const client = await Elements('YOUR_API_KEY', { env: 'production' });

await client.injectCheckoutElement({
  containerId: 'checkout-container',
  checkoutId: 'optional_checkout_id',  // Optional: load specific checkout
  hideHeader: false  // Optional: hide checkout header
});
```

#### With URL Parameter

Configure checkout to load from URL parameter:

```html
<script
  defer
  data-liquid-commerce-elements
  data-token="YOUR_API_KEY"
  data-env="production"
  data-checkout-container="checkout"
  data-checkout-param="lce_checkout"
  type="text/javascript"
  src="https://elements.reservebar-worker.workers.dev/all/elements.js"
></script>

<div id="checkout"></div>
```

Visit `https://yoursite.com/checkout?lce_checkout=checkout_abc123` to load that checkout.

### Redirect to Custom Checkout Page

Configure the cart to redirect to your checkout page instead of opening the drawer:

```javascript
const client = await Elements('YOUR_API_KEY', {
  env: 'production',
  checkout: {
    pageUrl: 'https://yoursite.com/checkout?lce_checkout={token}'
  }
});
```

Or with data attributes:

```html
<script
  defer
  data-liquid-commerce-elements
  data-token="YOUR_API_KEY"
  data-env="production"
  data-checkout-url="https://yoursite.com/checkout?lce_checkout={token}"
  type="text/javascript"
  src="https://elements.reservebar-worker.workers.dev/all/elements.js"
></script>
```

The `{token}` placeholder is replaced with the checkout token.

## Checkout Actions

### Open Checkout

```javascript
window.LiquidCommerce.elements.actions.checkout.openCheckout();
```

### Close Checkout

```javascript
window.LiquidCommerce.elements.actions.checkout.closeCheckout();
```

### Toggle Checkout

```javascript
window.LiquidCommerce.elements.actions.checkout.toggleCheckout();
```

### Exit Checkout

Navigate away from checkout (requires `exitUrl` configuration):

```javascript
window.LiquidCommerce.elements.actions.checkout.exitCheckout();
```

Configure exit URL:

```javascript
customTheme: {
  checkout: {
    layout: {
      exitUrl: 'https://yoursite.com/shop'
    }
  }
}
```

### Add Product to Checkout

Skip the cart and go directly to checkout:

```javascript
await window.LiquidCommerce.elements.actions.checkout.addProduct([
  {
    identifier: '00619947000020',
    fulfillmentType: 'shipping',
    quantity: 1
  }
], true);  // true = open checkout after adding
```

### Apply Promo Code

```javascript
await window.LiquidCommerce.elements.actions.checkout.applyPromoCode('WELCOME10');
```

### Remove Promo Code

```javascript
await window.LiquidCommerce.elements.actions.checkout.removePromoCode();
```

### Apply Gift Card

```javascript
await window.LiquidCommerce.elements.actions.checkout.applyGiftCard('GIFT-1234-5678');
```

### Remove Gift Card

```javascript
await window.LiquidCommerce.elements.actions.checkout.removeGiftCard('GIFT-1234-5678');
```

### Toggle Gift Mode

Enable/disable "Send as Gift" mode:

```javascript
// Enable gift mode
await window.LiquidCommerce.elements.actions.checkout.toggleIsGift(true);

// Disable gift mode
await window.LiquidCommerce.elements.actions.checkout.toggleIsGift(false);

// Toggle current state
await window.LiquidCommerce.elements.actions.checkout.toggleIsGift();
```

### Toggle Billing Same As Shipping

```javascript
// Use shipping address for billing
await window.LiquidCommerce.elements.actions.checkout.toggleBillingSameAsShipping(true);

// Use different billing address
await window.LiquidCommerce.elements.actions.checkout.toggleBillingSameAsShipping(false);
```

### Toggle Marketing Preferences

```javascript
// Opt into email marketing
await window.LiquidCommerce.elements.actions.checkout.toggleMarketingPreferences('canEmail', true);

// Opt into SMS marketing
await window.LiquidCommerce.elements.actions.checkout.toggleMarketingPreferences('canSms', true);
```

### Update Customer Information

Pre-fill customer information:

```javascript
window.LiquidCommerce.elements.actions.checkout.updateCustomerInfo({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  phone: '+15551234567',
  birthDate: '123 Main St',
  addressTwo: 'Apt 4',
  company: 'Acme Corp'
});
```

**Available fields:**
- `firstName`, `lastName`
- `email`, `phone`
- `birthDate`, `addressTwo`
- `company`

### Update Gift Information

Pre-fill gift recipient information:

```javascript
window.LiquidCommerce.elements.actions.checkout.updateGiftInfo({
  firstName: 'Jane',
  lastName: 'Smith',
  email: 'jane@example.com',
  phone: '+15559876543',
  message: 'Happy Birthday!',
  addressTwo: 'Suite 5B'
});
```

**Available fields:**
- `firstName`, `lastName`
- `email`, `phone`
- `message`
- `addressTwo`

### Update Billing Information

Pre-fill billing address:

```javascript
window.LiquidCommerce.elements.actions.checkout.updateBillingInfo({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  phone: '+15551234567',
  addressOne: '789 Elm St',
  addressTwo: 'Floor 2',
  city: 'Chicago',
  state: 'IL',
  zipCode: '60601'
});
```

**Available fields:**
- `firstName`, `lastName`
- `email`, `phone`, `company`
- `addressOne`, `addressTwo`
- `city`, `state`, `zipCode`

### Get Checkout Details

```javascript
const checkoutData = window.LiquidCommerce.elements.actions.checkout.getDetails();

console.log(checkoutData);
// {
//   token: 'abc123xyz',
//   cartId: 'cart_abc123',
//   items: [...],
//   amounts: {
//     subtotal: 9998,
//     tax: 800,
//     shipping: 500,
//     tip: 200,
//     total: 11498
//   },
//   customer: { ... },
//   shippingAddress: { ... },
//   isGift: false,
//   ...
// }
```

## Events

### Checkout Lifecycle

```javascript
window.addEventListener('lce:actions.checkout_loaded', (event) => {
  console.log('Checkout loaded');
});

window.addEventListener('lce:actions.checkout_opened', (event) => {
  console.log('Checkout opened');
});

window.addEventListener('lce:actions.checkout_closed', (event) => {
  console.log('Checkout closed');
});

window.addEventListener('lce:actions.checkout_failed', (event) => {
  console.error('Checkout failed:', event.detail.data.error);
});
```

### Customer Information

```javascript
window.addEventListener('lce:actions.checkout_customer_information_updated', (event) => {
  const { email, phone } = event.detail.data;
  console.log('Customer info updated:', email);
});
```

### Gift Information

```javascript
window.addEventListener('lce:actions.checkout_is_gift_toggled', (event) => {
  const { isGift } = event.detail.data;
  console.log('Gift mode:', isGift ? 'enabled' : 'disabled');
});

window.addEventListener('lce:actions.checkout_gift_information_updated', (event) => {
  console.log('Gift recipient updated');
});
```

### Billing Information

```javascript
window.addEventListener('lce:actions.checkout_billing_same_as_shipping_toggled', (event) => {
  const { billingSameAsShipping } = event.detail.data;
  console.log('Billing same as shipping:', billingSameAsShipping);
});

window.addEventListener('lce:actions.checkout_billing_information_updated', (event) => {
  console.log('Billing address updated');
});
```

### Marketing Preferences

```javascript
window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (event) => {
  const { field, active } = event.detail.data;
  console.log(`Marketing ${field}:`, active);
});
```

### Items Management

```javascript
window.addEventListener('lce:actions.checkout_item_removed', (event) => {
  const { itemId } = event.detail.data;
  console.log('Item removed:', itemId);
});

window.addEventListener('lce:actions.checkout_item_quantity_increase', (event) => {
  const { itemId, newQuantity } = event.detail.data;
  console.log(`Item ${itemId} quantity: ${newQuantity}`);
});

window.addEventListener('lce:actions.checkout_item_quantity_decrease', (event) => {
  const { itemId, newQuantity } = event.detail.data;
  console.log(`Item ${itemId} quantity: ${newQuantity}`);
});
```

### Tips

```javascript
window.addEventListener('lce:actions.checkout_tip_updated', (event) => {
  const { tip } = event.detail.data;
  console.log('Tip amount:', tip / 100);
});
```

### Payment & Submission

```javascript
window.addEventListener('lce:actions.checkout_submit_started', (event) => {
  console.log('Processing payment...');
  // Show loading state
});

window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
  const { orderId } = event.detail.data;
  console.log('Order completed:', orderId);
  // Redirect to confirmation page
});

window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
  const { error } = event.detail.data;
  console.error('Payment failed:', error);
  // Show error message
});
```

### Promo Codes

```javascript
window.addEventListener('lce:actions.checkout_promo_code_applied', (event) => {
  const { discount, newTotal } = event.detail.data;
  console.log(`Promo applied: $${discount / 100} off`);
});

window.addEventListener('lce:actions.checkout_promo_code_removed', (event) => {
  console.log('Promo code removed');
});

window.addEventListener('lce:actions.checkout_promo_code_failed', (event) => {
  const { error } = event.detail.data;
  console.error('Promo code failed:', error);
});
```

### Gift Cards

```javascript
window.addEventListener('lce:actions.checkout_gift_card_applied', (event) => {
  const { newTotal } = event.detail.data;
  console.log('Gift card applied, new total:', newTotal / 100);
});

window.addEventListener('lce:actions.checkout_gift_card_removed', (event) => {
  console.log('Gift card removed');
});

window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
  const { error } = event.detail.data;
  console.error('Gift card failed:', error);
});
```

### Product Add to Checkout

```javascript
window.addEventListener('lce:actions.checkout_product_add_success', (event) => {
  const { itemsAdded, identifiers } = event.detail.data;
  console.log(`Added ${itemsAdded} items to checkout`);
});

window.addEventListener('lce:actions.checkout_product_add_failed', (event) => {
  const { error } = event.detail.data;
  console.error('Failed to add to checkout:', error);
});
```

## Customization

### Theme Configuration

```javascript
const client = await Elements('YOUR_API_KEY', {
  env: 'production',
  customTheme: {
    checkout: {
      theme: {
        backgroundColor: '#ffffff'
      },
      layout: {
        allowGiftCards: true,
        exitUrl: 'https://yoursite.com/shop',
        continueShoppingUrl: 'https://yoursite.com/shop',
        drawerHeaderText: 'Checkout',
        placeOrderButtonText: 'Complete Purchase'
      }
    }
  }
});
```

## Payment Integration

The SDK uses Stripe for payment processing. Payment form is embedded and handles:
- Credit/debit cards
- Apple Pay (when available)
- Google Pay (when available)
- PCI compliance
- 3D Secure authentication

No additional Stripe integration code needed - it's built-in.

## Checkout Flow

### Standard Flow

1. Customer opens checkout (from cart or direct)
2. Reviews order summary
3. Enters shipping information
4. Enters payment information
5. Optionally enters billing address
6. Reviews total (with promo codes, gift cards, tips)
7. Places order
8. Sees order confirmation

### Gift Flow

1. Customer enables "Send as Gift"
2. Enters their billing/payment information
3. Enters recipient's shipping information
4. Adds gift message (optional)
5. Places order
6. Confirmation shows gift delivery details

## Presale Products

Checkouts with presale items show:
- Countdown timer for presale expiration
- Expected delivery date
- Special handling for presale orders

When presale expires:
- Shows expiration notice
- Disables checkout submission

## Best Practices

### Pre-fill Known Information

If you have customer data, pre-fill it:

```javascript
// After user logs in
if (userIsLoggedIn) {
  window.addEventListener('lce:actions.checkout_opened', () => {
    window.LiquidCommerce.elements.actions.checkout.updateCustomerInfo({
      firstName: currentUser.firstName,
      lastName: currentUser.lastName,
      email: currentUser.email,
      phone: currentUser.phone
    });
  });
}
```

### Track Conversion Funnel

```javascript
const checkoutFunnel = {
  loaded: false,
  infoEntered: false,
  paymentEntered: false,
  submitted: false
};

window.addEventListener('lce:actions.checkout_loaded', () => {
  checkoutFunnel.loaded = true;
  gtag('event', 'begin_checkout');
});

window.addEventListener('lce:actions.checkout_customer_information_updated', () => {
  if (!checkoutFunnel.infoEntered) {
    checkoutFunnel.infoEntered = true;
    gtag('event', 'checkout_progress', { step: 'customer_info' });
  }
});

window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
  gtag('event', 'purchase', {
    transaction_id: event.detail.data.orderId,
    value: event.detail.data.total / 100,
    currency: 'USD'
  });
});
```

### Handle Submission States

```javascript
window.addEventListener('lce:actions.checkout_submit_started', () => {
  // Disable navigation
  window.onbeforeunload = () => 'Payment in progress...';
  
  // Show loading overlay
  showGlobalLoadingOverlay('Processing your order...');
});

window.addEventListener('lce:actions.checkout_submit_completed', () => {
  // Re-enable navigation
  window.onbeforeunload = null;
  
  // Redirect to confirmation
  window.location.href = '/order-confirmation';
});

window.addEventListener('lce:actions.checkout_submit_failed', () => {
  // Re-enable navigation
  window.onbeforeunload = null;
  
  // Hide loading
  hideGlobalLoadingOverlay();
});
```

## Configuration Options

### Enable/Disable Features

```javascript
checkout: {
  layout: {
    allowGiftCards: true,       // Show gift card input
    emailOptIn: {
      show: true,              // Show email opt-in checkbox
      checked: false,            // Default unchecked
      text: 'Subscribe to our newsletter'
    },
    smsOptIn: {
      show: false,             // Hide SMS opt-in checkbox
      checked: false,          // Default unchecked
      text: 'Receive SMS updates'
    }
  }
}
```

### Button Text

```javascript
checkout: {
  layout: {
    placeOrderButtonText: 'Complete Purchase'
  }
}
```

## Troubleshooting

### Checkout Not Opening

1. Verify cart has items: `window.LiquidCommerce.elements.actions.cart.getDetails()`
2. Check for JavaScript errors in console
3. Ensure SDK is initialized: `window.LiquidCommerce.elements`
4. Try manually: `window.LiquidCommerce.elements.actions.checkout.openCheckout()`

### Payment Form Not Loading

1. Check internet connection (Stripe requires network)
2. Verify Stripe is not blocked by ad blockers
3. Check browser console for Stripe errors
4. Ensure your API key is valid

### Customer Info Not Pre-filling

1. Verify you're calling `updateCustomerInfo()` after checkout loads
2. Check field names match exactly (case-sensitive)
3. Ensure values are strings, not other types
4. Listen for checkout_opened event before updating

### Order Submission Failing

1. Check all required fields are filled
2. Verify payment information is valid
3. Look for validation errors in UI
4. Check console for detailed error messages
5. Ensure products are still available

## See Also

- [Cart Component](./cart-component.md) - Shopping cart functionality
- [Actions API](../api/actions/checkout-actions.md) - Checkout actions reference
- [Events](./events.md) - All available events
- [Theming](./theming.md) - Customize appearance
