> ## 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.

# Vanilla JavaScript Guide

> Use TagadaPay SDK without any framework

# Vanilla JavaScript / Standalone SDK

Use the TagadaPay SDK in **any JavaScript project** - no framework required!

<Info>
  **Perfect for:**

  * Pure HTML/CSS/JS sites
  * Server-rendered apps
  * Other frameworks (Svelte, Angular, Vue, etc.)
  * WordPress, Shopify, or any platform
</Info>

***

## Quick Start

### Installation

```bash theme={null}
npm install @tagadapay/plugin-sdk
```

### Basic Usage

```javascript theme={null}
import { createTagadaClient, FunnelActionType } from '@tagadapay/plugin-sdk/v2/standalone';

// 1. Create client - funnel auto-initializes!
const client = createTagadaClient({
  features: { funnel: true }
});

// 2. Subscribe to funnel state
client.funnel.subscribe((funnelState) => {
  if (funnelState.isInitialized && funnelState.context) {
    console.log('✅ Funnel ready!', funnelState.context);
    // Render your UI here
  }
});

// 3. Use funnel methods
document.getElementById('pay-btn').onclick = async () => {
  await client.funnel.navigate({
    type: FunnelActionType.PAYMENT_SUCCESS,
    data: {
      order: { id: 'ord_123', amount: 99.99 }
    }
  });
  // Auto-redirects to next page!
};
```

<Check>
  **That's it!** No manual initialization, no complex state management. The SDK handles everything automatically.
</Check>

***

## How It Works

The SDK automatically:

1. ✅ Creates an anonymous session
2. ✅ Initializes the funnel (when enabled)
3. ✅ Loads configuration and static resources
4. ✅ Handles navigation and redirects

All you do is:

1. Create the client
2. Subscribe to get updates
3. Use `client.funnel.navigate()` to move between steps

***

## Complete Example

Here's a full checkout page in vanilla JavaScript:

```javascript theme={null}
import { createTagadaClient, FunnelActionType } from '@tagadapay/plugin-sdk/v2/standalone';

// Create client
const client = createTagadaClient({
  features: { funnel: true }
});

// Subscribe to funnel ready state
client.funnel.subscribe((funnelState) => {
  if (funnelState.isInitialized && funnelState.context) {
    renderCheckout(funnelState.context);
  } else if (funnelState.error) {
    showError(funnelState.error.message);
  }
});

function renderCheckout(context) {
  // Get static resources (configured in CRM)
  const offerId = context.static?.offer?.id;
  
  // Get context data (from previous steps)
  const order = context.resources?.order;
  const customer = context.resources?.customer;
  
  // Render your UI
  document.getElementById('customer-email').textContent = customer?.email || 'Guest';
  document.getElementById('order-total').textContent = `$${order?.amount || 0}`;
  
  // Setup payment button
  document.getElementById('pay-btn').onclick = async () => {
    try {
      await client.funnel.navigate({
        type: FunnelActionType.PAYMENT_SUCCESS,
        data: {
          resources: {
            order: {
              id: 'ord_123',
              amount: 4900,
              currency: 'USD'
            },
            customer: {
              email: document.getElementById('email-input').value
            }
          }
        }
      });
      // Automatically redirects to thank you page!
    } catch (error) {
      alert('Payment failed: ' + error.message);
    }
  };
}

function showError(message) {
  document.getElementById('error').textContent = message;
}
```

***

## Available Methods

### Client State

```javascript theme={null}
// Get current state
const state = client.getState();
console.log(state.store);     // Store info
console.log(state.customer);  // Customer info
console.log(state.session);   // Session info

// Subscribe to state changes
client.subscribe((state) => {
  console.log('State updated:', state);
});
```

### Funnel Methods

```javascript theme={null}
// Navigate to next step
await client.funnel.navigate({
  type: FunnelActionType.PAYMENT_SUCCESS,
  data: { /* your data */ }
});

// Update funnel context
await client.funnel.updateContext({
  metadata: {
    customField: 'value'
  }
});

// Get current funnel state
const funnelState = client.funnel.getState();
console.log(funnelState.context);      // Current funnel context
console.log(funnelState.isLoading);    // Loading state
console.log(funnelState.error);        // Error if any
```

***

## Funnel Action Types

All available action types for `funnel.navigate()`:

```javascript theme={null}
FunnelActionType.PAYMENT_SUCCESS     // Payment completed
FunnelActionType.PAYMENT_FAILED      // Payment failed
FunnelActionType.OFFER_ACCEPTED      // Upsell accepted
FunnelActionType.OFFER_DECLINED      // Upsell declined
FunnelActionType.FORM_SUBMITTED      // Form completed
FunnelActionType.SKIP                // Skip current step
```

***

## Working with Static Resources

Static resources are configured by merchants in the CRM. Your code accesses them dynamically:

```javascript theme={null}
client.funnel.subscribe((funnelState) => {
  if (funnelState.context) {
    // Access static resources
    const offerId = funnelState.context.static?.offer?.id;
    const productId = funnelState.context.static?.product?.id;
    const variantId = funnelState.context.static?.variant?.id;
    
    // Fetch the actual offer data
    if (offerId) {
      fetchOffer(offerId).then(offer => {
        document.getElementById('offer-title').textContent = offer.title;
        document.getElementById('offer-price').textContent = `$${offer.price}`;
      });
    }
  }
});
```

### Local Testing

For local development, create `config/resources.static.json`:

```json theme={null}
{
  "offer": {
    "id": "offer_test123"
  },
  "product": {
    "id": "prod_test456"
  }
}
```

The SDK automatically loads this in local dev!

***

## Configuration

```javascript theme={null}
const client = createTagadaClient({
  // Environment (auto-detected by default)
  environment: 'production',  // 'local' | 'development' | 'production'
  
  // Debug mode (auto-enabled in local dev)
  debugMode: true,
  
  // Features
  features: {
    funnel: true,  // Enable funnel navigation
  },
  
  // Local config name (for testing different presets)
  localConfig: 'premium',  // Loads config/premium.config.json
});
```

***

## Error Handling

```javascript theme={null}
// Funnel errors
client.funnel.subscribe((funnelState) => {
  if (funnelState.error) {
    console.error('Funnel error:', funnelState.error);
    showErrorMessage(funnelState.error.message);
  }
  
  if (funnelState.sessionError) {
    console.error('Session error:', funnelState.sessionError);
    // Session initialization failed
  }
});

// Navigation errors
try {
  await client.funnel.navigate({
    type: FunnelActionType.PAYMENT_SUCCESS,
    data: { /* ... */ }
  });
} catch (error) {
  console.error('Navigation failed:', error);
  alert('Failed to proceed: ' + error.message);
}
```

***

## TypeScript Support

Full TypeScript support included:

```typescript theme={null}
import { 
  createTagadaClient, 
  FunnelActionType,
  type TagadaState,
  type SimpleFunnelContext 
} from '@tagadapay/plugin-sdk/v2/standalone';

const client = createTagadaClient({
  features: { funnel: true }
});

client.subscribe((state: TagadaState) => {
  // Fully typed!
  console.log(state.store?.id);
  console.log(state.customer?.email);
});

client.funnel.subscribe((funnelState) => {
  if (funnelState.context) {
    const context: SimpleFunnelContext = funnelState.context;
    // All context properties are typed
  }
});
```

***

## Real-World Example: Checkout Page

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <title>Checkout</title>
</head>
<body>
  <div id="app">
    <div id="loading">Loading...</div>
    <div id="checkout" style="display: none;">
      <h1>Checkout</h1>
      <div id="order-summary"></div>
      <input id="email" type="email" placeholder="Email" />
      <button id="pay-btn">Pay Now</button>
    </div>
    <div id="error"></div>
  </div>
  
  <script type="module" src="/main.js"></script>
</body>
</html>
```

```javascript theme={null}
// main.js
import { createTagadaClient, FunnelActionType } from '@tagadapay/plugin-sdk/v2/standalone';

const client = createTagadaClient({
  features: { funnel: true }
});

let globalOrder = null;

// Wait for funnel ready
client.funnel.subscribe((funnelState) => {
  if (funnelState.isInitialized && funnelState.context) {
    document.getElementById('loading').style.display = 'none';
    document.getElementById('checkout').style.display = 'block';
    
    // Get order from context (if coming from previous step)
    globalOrder = funnelState.context.resources?.order || {
      id: 'new-order',
      amount: 4900,
      currency: 'USD'
    };
    
    document.getElementById('order-summary').innerHTML = `
      <p>Total: $${(globalOrder.amount / 100).toFixed(2)}</p>
    `;
  } else if (funnelState.error) {
    document.getElementById('loading').style.display = 'none';
    document.getElementById('error').textContent = funnelState.error.message;
  }
});

// Handle payment
document.getElementById('pay-btn').onclick = async () => {
  const email = document.getElementById('email').value;
  
  if (!email) {
    alert('Please enter your email');
    return;
  }
  
  try {
    await client.funnel.navigate({
      type: FunnelActionType.PAYMENT_SUCCESS,
      data: {
        resources: {
          order: {
            ...globalOrder,
            status: 'paid'
          },
          customer: {
            email,
            id: `cus_${Date.now()}`
          }
        }
      }
    });
    // Auto-redirects to next page (upsell or thank you)
  } catch (error) {
    alert('Payment failed: ' + error.message);
  }
};
```

***

## Comparison: Before vs After

### ❌ Old Way (Too Complex)

```javascript theme={null}
const client = createTagadaClient({ features: { funnel: true } });

// Wait for client ready
client.subscribe(async (state) => {
  if (state.isInitialized && state.auth.session && state.store) {
    // Manual funnel initialization
    const context = await client.funnel.autoInitialize(
      { customerId: state.auth.session.customerId },
      { id: state.store.id, accountId: state.store.accountId }
    );
    
    // Now render UI...
  }
});
```

### ✅ New Way (Simple!)

```javascript theme={null}
const client = createTagadaClient({ features: { funnel: true } });

// Funnel auto-initializes - just subscribe!
client.funnel.subscribe((funnelState) => {
  if (funnelState.isInitialized && funnelState.context) {
    // Render UI immediately
  }
});
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Build a Funnel" icon="route" href="/developer-tools/sdk/tutorial">
    Follow the step-by-step tutorial
  </Card>

  <Card title="Funnel Resources" icon="database" href="/developer-tools/sdk/funnel-resources">
    Learn about passing data between steps
  </Card>

  <Card title="API Reference" icon="book" href="/developer-tools/sdk/api">
    Explore all available methods
  </Card>

  <Card title="Examples" icon="code" href="https://github.com/tagadapay/examples">
    See complete examples
  </Card>
</CardGroup>
