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

# Funnel Orchestrator

> Create multi-step checkout funnels with the API — define steps, connect pages, and track conversions

# Funnel Orchestrator

<Info>
  **What is a funnel?** A funnel is a sequence of pages your customer walks through: landing page → checkout → upsell offer → thank you. The orchestrator manages the order, the navigation, the analytics, and the A/B testing — all in one place.
</Info>

## Why Use the Funnel Orchestrator?

Without a funnel, your checkout is a single isolated page. The customer pays and lands on a generic confirmation. That works, but you're leaving money and insights on the table.

With the orchestrator you get:

| Capability               | What it does                                                                 |
| ------------------------ | ---------------------------------------------------------------------------- |
| **Multi-step flows**     | Chain pages together: checkout → upsell → downsell → thank you               |
| **Automatic navigation** | The SDK moves the customer to the next step — no manual redirects            |
| **Session tracking**     | One session follows the customer across all steps (device, UTMs, timestamps) |
| **Conversion analytics** | See where customers drop off and which steps convert                         |
| **A/B testing per step** | Split traffic on any step — different pages, different configs               |
| **Automatic routing**    | When you save a funnel, routes are mounted/unmounted for you                 |

**In short:** the orchestrator turns a standalone page into a real sales flow with analytics.

***

## Core Concepts (5-minute overview)

### Funnel = Graph of Nodes and Edges

A funnel is a directed graph:

```
[Checkout] ──→ [Upsell Offer] ──→ [Thank You]
   (entry)                          (conversion)
```

* **Nodes** are the steps (checkout page, upsell page, thank you page, etc.)
* **Edges** are the connections between steps (what comes after what)

### Node Types

| Type               | Purpose                                                       |
| ------------------ | ------------------------------------------------------------- |
| `checkout`         | Payment page — collects customer info and processes the order |
| `thankyou`         | Confirmation page — shown after a successful purchase         |
| `offer` / `upsell` | Post-purchase offer — shown between checkout and thank you    |
| `downsell`         | Alternative offer if the customer declines the upsell         |
| `landing`          | Pre-checkout page (landing page, product page, etc.)          |

### What Happens Under the Hood

When you create or update a funnel via the API:

1. TagadaPay saves the funnel configuration (nodes + edges)
2. For each step, it **automatically mounts** the right plugin page at the right URL path
3. The SDK reads the funnel config at runtime and handles navigation between steps
4. Analytics events are tracked automatically (views, enters, conversions)

You don't need to manually mount routes — the funnel orchestrator does it for you.

***

## Tutorial: Create Your First Funnel

We'll create the most common funnel: **Checkout → Thank You**.

### Prerequisites

* A TagadaPay account with an API key
* A store (you can [create one via the API](/api-reference/stores/create-a-store) or from the CRM)
* At least one deployed plugin (the built-in `tagada-native` checkout is auto-provisioned for you)

<Note>
  If you don't have a custom plugin deployed, TagadaPay will automatically inject its built-in checkout plugin (`tagada-native`) into your funnel steps. You can start without deploying anything.
</Note>

### Step 1 — Create the Funnel

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://app.tagadapay.com/api/public/v1/funnels \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "storeId": "store_abc123",
      "config": {
        "name": "My First Funnel",
        "version": "1.0.0",
        "nodes": [
          {
            "id": "step_checkout",
            "name": "Checkout",
            "type": "checkout",
            "isEntry": true,
            "config": {
              "path": "/checkout"
            }
          },
          {
            "id": "step_thankyou",
            "name": "Thank You",
            "type": "thankyou",
            "isConversion": true,
            "config": {
              "path": "/thankyou"
            }
          }
        ],
        "edges": [
          {
            "id": "edge_1",
            "source": "step_checkout",
            "target": "step_thankyou"
          }
        ]
      },
      "isDefault": true
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://app.tagadapay.com/api/public/v1/funnels', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      storeId: 'store_abc123',
      config: {
        name: 'My First Funnel',
        version: '1.0.0',
        nodes: [
          {
            id: 'step_checkout',
            name: 'Checkout',
            type: 'checkout',
            isEntry: true,
            config: { path: '/checkout' },
          },
          {
            id: 'step_thankyou',
            name: 'Thank You',
            type: 'thankyou',
            isConversion: true,
            config: { path: '/thankyou' },
          },
        ],
        edges: [
          { id: 'edge_1', source: 'step_checkout', target: 'step_thankyou' },
        ],
      },
      isDefault: true,
    }),
  });

  const funnel = await response.json();
  console.log(funnel.id); // "funnelv2_..."
  ```
</CodeGroup>

**What just happened:**

* TagadaPay created a funnel with two steps
* It automatically provisioned the native checkout plugin for both steps
* Routes were mounted so `/checkout` and `/thankyou` resolve to the right pages
* This funnel is marked as the **default** — it's the one used when a customer hits your store's checkout URL

### Step 2 — Verify Your Funnel

```bash theme={null}
curl https://app.tagadapay.com/api/public/v1/funnels/FUNNEL_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

The response includes the full config with the auto-injected plugin instance IDs:

```json theme={null}
{
  "id": "funnelv2_abc123",
  "name": "My First Funnel",
  "active": true,
  "config": {
    "nodes": [
      {
        "id": "step_checkout",
        "name": "Checkout",
        "type": "checkout",
        "isEntry": true,
        "config": {
          "path": "/checkout",
          "pluginId": "tagada-native",
          "instanceId": "mgwf1ft7iws46-6d4feb54",
          "instanceVersion": "1.0.0"
        }
      }
    ],
    "edges": [...]
  }
}
```

<Tip>
  Notice the `pluginId`, `instanceId`, and `instanceVersion` — TagadaPay injected those automatically because the step type is `checkout`. You didn't have to deploy or configure anything.
</Tip>

### Step 3 — Test with a Preview Session

Preview sessions let you test the funnel without real payments:

```bash theme={null}
curl -X POST https://app.tagadapay.com/api/public/v1/funnels/FUNNEL_ID/preview-session \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "storeId": "store_abc123",
    "funnelId": "funnelv2_abc123",
    "stepId": "step_checkout"
  }'
```

Response:

```json theme={null}
{
  "sessionId": "fs_123456789",
  "funnelId": "funnelv2_abc123",
  "stepId": "step_checkout",
  "token": "eyJhbG...",
  "customerId": "cus_preview_123"
}
```

Use the `sessionId` and `token` to load the checkout page in preview mode.

***

## Adding an Upsell Step

The real power of funnels comes from **post-purchase flows**. Let's add an upsell offer between checkout and thank you.

Use the [Update Funnel](/api-reference/funnels/update-funnel-with-routing) endpoint:

```bash theme={null}
curl -X PUT https://app.tagadapay.com/api/public/v1/funnels/FUNNEL_ID \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "funnelId": "funnelv2_abc123",
    "storeId": "store_abc123",
    "config": {
      "name": "Checkout with Upsell",
      "version": "1.1.0",
      "nodes": [
        {
          "id": "step_checkout",
          "name": "Checkout",
          "type": "checkout",
          "isEntry": true,
          "config": { "path": "/checkout" }
        },
        {
          "id": "step_offer",
          "name": "Special Offer",
          "type": "offer",
          "config": { "path": "/offer" }
        },
        {
          "id": "step_thankyou",
          "name": "Thank You",
          "type": "thankyou",
          "isConversion": true,
          "config": { "path": "/thankyou" }
        }
      ],
      "edges": [
        { "id": "edge_1", "source": "step_checkout", "target": "step_offer" },
        { "id": "edge_2", "source": "step_offer", "target": "step_thankyou" }
      ]
    }
  }'
```

The response tells you exactly what the orchestrator did:

```json theme={null}
{
  "funnel": { "id": "funnelv2_abc123", "name": "Checkout with Upsell" },
  "operations": [
    { "type": "skip", "stepId": "step_checkout", "status": "completed" },
    { "type": "mount", "stepId": "step_offer", "status": "completed" },
    { "type": "skip", "stepId": "step_thankyou", "status": "completed" }
  ],
  "summary": { "total": 3, "mounted": 1, "unmounted": 0, "swapped": 0, "failed": 0 }
}
```

The orchestrator:

* **Skipped** the checkout and thank you steps (already mounted)
* **Mounted** the new offer step at `/offer`

Your funnel is now: **Checkout → Upsell Offer → Thank You**.

***

## A/B Testing a Step

You can split traffic on any step using **variants**. Each variant can point to a different page design (different deployment) or the same page with a different config.

```json theme={null}
{
  "id": "step_checkout",
  "name": "Checkout",
  "type": "checkout",
  "isEntry": true,
  "splitType": "weighted",
  "variants": [
    {
      "id": "variant_a",
      "label": "Original Design",
      "percentage": 50,
      "config": {
        "path": "/checkout",
        "pluginId": "tagada-native",
        "instanceId": "instance_original"
      }
    },
    {
      "id": "variant_b",
      "label": "New Design",
      "percentage": 50,
      "config": {
        "path": "/checkout",
        "pluginId": "my-custom-checkout",
        "instanceId": "instance_new_design"
      }
    }
  ]
}
```

| Split Type | How it works                                                                 |
| ---------- | ---------------------------------------------------------------------------- |
| `weighted` | Traffic is split by percentage (e.g., 50/50, 90/10)                          |
| `geo`      | Traffic is split by visitor region (use the `regions` field on each variant) |

Visitors are sticky — once assigned a variant, they see the same one on return.

***

## Step Configuration (Runtime Config)

Each step can have runtime config injected when the page loads — tracking pixels, payment flows, and custom scripts:

```json theme={null}
{
  "id": "step_checkout",
  "name": "Checkout",
  "type": "checkout",
  "config": {
    "path": "/checkout",
    "stepConfig": {
      "payment": {
        "paymentFlowId": "pf_stripe_live"
      },
      "scripts": [
        {
          "name": "Facebook Pixel",
          "enabled": true,
          "content": "<script>fbq('track', 'InitiateCheckout');</script>",
          "position": "body-end"
        }
      ],
      "pixels": {
        "facebook": {
          "enabled": true,
          "pixelId": "123456789",
          "events": {
            "PageView": true,
            "InitiateCheckout": true,
            "Purchase": true
          }
        }
      }
    }
  }
}
```

The step config is available in the Plugin SDK via `useStepConfig()` or `window.__TGD_STEP_CONFIG__`. See [Step Config & Script Injection](/developer-tools/sdk/introduction#step-config--script-injection) for details.

***

## Tracking Funnel Events

The SDK tracks events automatically when used inside a funnel. If you need manual tracking (e.g., from a server or external page), use the [Track Funnel Step](/api-reference/funnel-tracking/track-funnel-step-event) endpoint:

```bash theme={null}
curl -X POST https://app.tagadapay.com/api/public/v1/funnel-tracking/step \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "eventType": "convert",
    "storeId": "store_abc123",
    "stepId": "step_thankyou",
    "stepName": "Thank You",
    "stepType": "thankyou",
    "funnelId": "funnelv2_abc123",
    "funnelSessionId": "fs_1234567890_abc123",
    "customerId": "cus_123",
    "isConversionStep": true,
    "orderId": "order_abc",
    "orderAmount": 4999,
    "orderCurrency": "USD"
  }'
```

| Event Type | When to use                                         |
| ---------- | --------------------------------------------------- |
| `view`     | Page was displayed (impression)                     |
| `enter`    | Customer navigated to the step                      |
| `convert`  | Customer completed the step's goal (e.g., purchase) |
| `custom`   | Any custom event you want to track                  |

***

## Debugging a Funnel Session

To inspect what happened in a customer's session:

```bash theme={null}
curl https://app.tagadapay.com/api/public/v1/funnel-sessions/SESSION_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

This returns the full session data: current step, furthest step reached, customer history, timestamps, metadata, and resources. Useful for debugging why a customer dropped off or got stuck.

***

## Complete API Reference

| Endpoint                                                                                 | Method | What it does                                      |
| ---------------------------------------------------------------------------------------- | ------ | ------------------------------------------------- |
| [`/stores/{storeId}/funnels`](/api-reference/funnels/list-funnels-for-a-store)           | GET    | List all funnels for a store                      |
| [`/funnels`](/api-reference/funnels/create-a-new-funnel)                                 | POST   | Create a new funnel                               |
| [`/funnels/{id}`](/api-reference/funnels/get-funnel-by-id)                               | GET    | Get funnel details                                |
| [`/funnels/{funnelId}`](/api-reference/funnels/update-funnel-with-routing)               | PUT    | Update funnel (auto-mounts routes)                |
| [`/funnels/{funnelId}/promote`](/api-reference/funnels/promote-funnel-to-production)     | POST   | Publish the staging config to a production domain |
| [`/funnels/{funnelId}`](/api-reference/funnels/delete-a-funnel)                          | DELETE | Delete funnel and clean up routes                 |
| [`/funnels/{funnelId}/preview-session`](/api-reference/funnels/create-a-preview-session) | POST   | Create a test session                             |
| [`/funnel-sessions/{sessionId}`](/api-reference/funnel-sessions/get-funnel-session-data) | GET    | Debug a session                                   |
| [`/funnel-tracking/step`](/api-reference/funnel-tracking/track-funnel-step-event)        | POST   | Track analytics events                            |

***

## Recap

```
1. Create funnel      →  Define nodes (steps) and edges (flow)
2. TagadaPay mounts   →  Routes and plugins are configured automatically
3. Customer visits    →  SDK handles navigation between steps
4. You track results  →  Conversion analytics per step, per variant
5. Iterate            →  Update the funnel, add steps, split test
```

<CardGroup cols={2}>
  <Card title="Funnel Lifecycle: Save, Publish & Go-Live" icon="rocket" href="/developer-tools/funnels/funnel-lifecycle">
    Duplicate, preview on staging, and promote to a production domain
  </Card>

  <Card title="Plugin SDK" icon="puzzle-piece" href="/developer-tools/sdk/introduction">
    Build the pages that power each step
  </Card>

  <Card title="Hosting & A/B Testing" icon="flask-vial" href="/developer-tools/hosting/deploy-and-ab-test">
    Host any page and run split tests
  </Card>

  <Card title="Direct Link Guide" icon="link" href="/developer-tools/web-integration/trigger-checkout-from-website">
    Generate checkout URLs from any website
  </Card>

  <Card title="External Page Tracker" icon="radar" href="/developer-tools/web-integration/external-page-tracker">
    Connect external pages to the funnel
  </Card>
</CardGroup>
