# Checkout Actions API

Checkout actions allow you to programmatically control the checkout flow.

## Navigation Actions

### actions.checkout.openCheckout()

```typescript
openCheckout(): void
```

Opens the checkout drawer or navigates to checkout page.

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

### actions.checkout.closeCheckout()

```typescript
closeCheckout(): void
```

Closes the checkout drawer.

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

### actions.checkout.toggleCheckout()

```typescript
toggleCheckout(): void
```

Toggles checkout open/closed.

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

### actions.checkout.exitCheckout()

```typescript
exitCheckout(): void
```

Navigates away from checkout (requires `exitUrl` configuration).

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

## Product Actions

### actions.checkout.addProduct()

```typescript
addProduct(params: IAddProductParams[], openCheckout?: boolean): Promise<void>
```

Add products directly to checkout, bypassing the cart.

`IAddProductParams.engravingLines?: string[]` — optional engraving. Same rules as [`actions.cart.addProduct()`](./cart-actions.md#actionscartaddproduct): invalid input is ignored, blanks stripped, lines clamped to the product's `maxLines` / `maxCharsPerLine`, and engraving is dropped (without failing) when the product, variant, or fulfillment doesn't support it.

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

// With engraving
await window.LiquidCommerce.elements.actions.checkout.addProduct([
  {
    identifier: '00619947000020',
    fulfillmentType: 'shipping',
    quantity: 1,
    engravingLines: ['For Dad']
  }
], true);
```

### actions.checkout.addAnonymousProduct()

```typescript
addAnonymousProduct(
  params: IAnonymousCheckoutAddProductParams
): Promise<IAnonymousCheckoutAddProductResponse>
```

Add a product to checkout without requiring a cart session. Used for direct-to-checkout flows.

```javascript
const result = await window.LiquidCommerce.elements.actions.checkout
  .addAnonymousProduct({
    identifier: '00619947000020',
    fulfillmentType: 'shipping',
    quantity: 1
  });
```

## Promo & Gift Card Actions

### actions.checkout.applyPromoCode()

```typescript
applyPromoCode(promoCode: string): Promise<void>
```

Apply a promo code during checkout.

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

### actions.checkout.removePromoCode()

```typescript
removePromoCode(): Promise<void>
```

Remove the active promo code.

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

### actions.checkout.applyGiftCard()

```typescript
applyGiftCard(code: string): Promise<void>
```

Apply a gift card.

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

### actions.checkout.removeGiftCard()

```typescript
removeGiftCard(code: string): Promise<void>
```

Remove a gift card.

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

## Toggle Actions

### actions.checkout.toggleIsGift()

```typescript
toggleIsGift(active?: boolean): Promise<void>
```

Enable/disable gift mode.

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

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

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

### actions.checkout.toggleBillingSameAsShipping()

```typescript
toggleBillingSameAsShipping(active?: boolean): Promise<void>
```

Set whether billing address matches 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);
```

### actions.checkout.toggleMarketingPreferences()

```typescript
toggleMarketingPreferences(field: 'canEmail' | 'canSms', active: boolean): Promise<void>
```

Set marketing opt-in 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);
```

## Form Update Actions

### actions.checkout.updateCustomerInfo()

```typescript
updateCustomerInfo(params: Record<CustomerFieldName, string>): void
```

Pre-fill customer information.

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

```javascript
window.LiquidCommerce.elements.actions.checkout.updateCustomerInfo({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  phone: '+15551234567',
  birthdate: '1990-01-01',
  addressTwo: 'Apt 4B',
  company: 'Acme Corp'
});
```

### actions.checkout.updateBillingInfo()

```typescript
updateBillingInfo(params: Record<BillingFieldName, string>): void
```

Pre-fill billing address.

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

```javascript
window.LiquidCommerce.elements.actions.checkout.updateBillingInfo({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  phone: '+15551234567',
  company: 'Acme Corp',
  addressOne: '123 Main St',
  addressTwo: 'Apt 4B',
  city: 'New York',
  state: 'NY',
  zipCode: '10001'
});
```

### actions.checkout.updateGiftInfo()

```typescript
updateGiftInfo(params: Record<GiftFieldName, string>): void
```

Pre-fill gift recipient information.

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

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

## Payment Method

### actions.checkout.setSavedPaymentMethod()

```typescript
setSavedPaymentMethod(params: {
  id: string;
  card: {
    brand: string;
    last4: string;
    expMonth?: string | number;
    expYear?: string | number;
  };
}): void
```

Pre-select a saved payment method for the checkout. When set, the payment step renders a read-only card summary (e.g. `Visa ending in 4242`) instead of the Stripe card form, and the shopper places the order without re-entering card details. The `id` is bound to the checkout when the payment form is saved.

`id` must be a payment method the backend already holds for the checkout's customer (for example, a card fetched server-side and handed to the page). If the backend does not recognize the `id` for this checkout's customer, saving the payment step fails with an error (`The selected payment method could not be applied to this checkout.`) and the order cannot be placed — pass only a payment method confirmed to belong to the customer. The `card` fields are used only to render the summary. It can be set at any time — before opening checkout, or while it is open — and the payment step updates accordingly. The selection persists across a cart reset within the session.

```javascript
window.LiquidCommerce.elements.actions.checkout.setSavedPaymentMethod({
  id: 'pm_123',
  card: { brand: 'Visa', last4: '4242', expMonth: '12', expYear: '30' }
});
```

### actions.checkout.clearSavedPaymentMethod()

```typescript
clearSavedPaymentMethod(): void
```

Remove a previously set saved payment method, restoring the Stripe card-entry form.

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

## Data Retrieval

### actions.checkout.getDetails()

```typescript
getDetails(): ICheckoutDetailsEventData
```

Retrieve current checkout information.

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

console.log(`Cart ID: ${checkout.cartId}`);
console.log(`Total: $${checkout.amounts.total / 100}`);
console.log(`Items: ${checkout.items.length}`);
console.log(`Is Gift: ${checkout.isGift}`);
```

**Returns:**

```typescript
interface ICheckoutDetailsEventData {
  cartId: string;
  items: ICheckoutItem[];
  amounts: {
    subtotal: number;
    tax: number;
    shipping: number;
    tip: number;
    total: number;
  };
  customer: ICustomerInfo;
  shippingAddress: IAddress;
  billingAddress?: IAddress;
  isGift: boolean;
  giftRecipient?: IGiftRecipient;
  promoCode?: IPromoCode;
  giftCards: IGiftCard[];
  // ... additional fields
}
```

### actions.checkout.getProductAvailabilityByState()

```typescript
getProductAvailabilityByState(
  identifiers: string[],
  state?: string
): Promise<IProductAvailabilityResponse>
```

Check product availability across states from the checkout context.

```javascript
const availability = await window.LiquidCommerce.elements.actions.checkout
  .getProductAvailabilityByState(['00619947000020'], 'CA');
```

| Parameter     | Type     | Required | Description                          |
|---------------|----------|----------|--------------------------------------|
| `identifiers` | string[] | Yes      | Array of product UPCs, SKUs, or IDs  |
| `state`       | string   | No       | Two-letter state code (e.g., `'NY'`) |

## Use Cases

### Pre-fill for Logged-In Users

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

### Track Checkout Progress

```javascript
window.addEventListener('lce:actions.checkout_customer_information_updated', () => {
  gtag('event', 'checkout_progress', { step: 'customer_info' });
});

window.addEventListener('lce:actions.checkout_submit_started', () => {
  gtag('event', 'checkout_progress', { step: 'payment' });
});

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

### Gift Flow

```javascript
document.getElementById('gift-checkbox').addEventListener('change', async (e) => {
  await window.LiquidCommerce.elements.actions.checkout.toggleIsGift(e.target.checked);
  
  if (e.target.checked) {
    showGiftForm();
  } else {
    hideGiftForm();
  }
});
```

### Auto-Apply Campaign Codes

```javascript
const params = new URLSearchParams(window.location.search);
const campaignCode = params.get('promo');

if (campaignCode) {
  window.addEventListener('lce:actions.checkout_opened', async () => {
    try {
      await window.LiquidCommerce.elements.actions.checkout.applyPromoCode(campaignCode);
    } catch (error) {
      console.log('Invalid campaign code');
    }
  });
}
```

## Events

Checkout actions trigger numerous events. See [Checkout Events](../../guides/events.md#checkout-events) for complete list.

Key events:
- `checkout_opened`, `checkout_closed`
- `checkout_customer_information_updated`
- `checkout_submit_started`, `checkout_submit_completed`, `checkout_submit_failed`
- `checkout_promo_code_applied`, `checkout_promo_code_failed`
- `checkout_gift_card_applied`, `checkout_gift_card_failed`

## See Also

- [Checkout Component Guide](../../guides/checkout-component.md)
- [Checkout Events](../../guides/events.md#checkout-events)
- [Cart Actions](./cart-actions.md)
