Skip to content
โ†All Docs

Funnel Analysis

Track how users move through your app. Set up funnels with a single AI prompt โ€” no manual instrumentation needed.

Funnel Analysis

Cloud feature โ€” Funnel analysis is available on Pro and Team plans. See Pricing for details.

A funnel shows how users move through a sequence of steps in your app. Think of it like a real funnel: lots of people enter at the top, and fewer make it to the bottom. The ones who leave? That's your drop-off. The ones who make it through? That's your conversion.

If you're building a SaaS app, a funnel might look like:

Landing Page โ†’ Signup Form โ†’ Email Verified โ†’ First Project Created
    1000           420            310                 85

That tells you: 42% of visitors start signing up, but only 8.5% finish onboarding. Now you know where to focus.

Why funnels matter for vibe-coded apps

When you're building fast with AI coding tools, you ship features quickly โ€” but you often skip instrumentation. You have no idea if users are actually completing the flows you built.

Funnels answer the question: "Are people doing the thing I built this for?"

Without them, you're guessing. With them, you know exactly where users get stuck, bail out, or hit a wall.

How VibePing's prompt-first setup works

Most analytics tools make you manually add tracking calls, then manually define funnels in a dashboard. That's tedious and error-prone.

VibePing flips this. Here's the idea:

  1. You tell VibePing what AI coding tool you're using and what kind of app you're building
  2. VibePing generates a prompt tailored to your setup
  3. You paste that prompt into your AI coding tool (Lovable, Cursor, Bolt.new, Replit, etc.)
  4. Your AI tool scans your codebase, adds vibeping.track() calls at the right places, and outputs a JSON file
  5. You paste that JSON back into VibePing
  6. Done โ€” funnels and goals are set up

Your AI coding tool does the heavy lifting. You just copy-paste twice.

Step-by-step setup guide

1. Go to /funnels in the dashboard

Open your VibePing dashboard and click Funnels in the sidebar, or go directly to /funnels. If you don't have any funnels yet, you'll see an empty state with a Set Up Funnels button.

2. Pick your AI tool and app type

Click Set Up Funnels to open the wizard. You'll see two choices:

AI coding tool โ€” Pick the one you're using:

  • Lovable
  • Cursor
  • Bolt.new
  • Replit
  • Other (generic prompt)

App type โ€” Pick what best describes your app:

  • SaaS โ€” Signup, onboarding, upgrades
  • E-Commerce โ€” Browse, cart, checkout
  • Content/Media โ€” Read, subscribe, share
  • Marketplace โ€” Buy, sell, transact
  • Other โ€” General app flows

These choices shape the prompt. A SaaS prompt looks for signup and onboarding flows. An e-commerce prompt looks for cart and checkout flows. Pick the closest match โ€” you can always edit later.

3. Copy the generated prompt

Click Next and you'll see a prompt generated for your specific setup. It includes:

  • Instructions to add the VibePing SDK script tag (with your project's API key pre-filled)
  • Directions to scan your codebase and add vibeping.track() calls
  • App-specific flow patterns to look for
  • Rules for event naming (snake_case, no dynamic values in names)
  • The exact JSON output format VibePing expects

Click Copy Prompt to copy it to your clipboard.

4. Paste into your AI coding tool

Switch to your AI coding tool and paste the prompt. The AI will:

  1. Check if the VibePing script tag is already in your HTML โ€” if not, add it
  2. Scan your codebase for user flows that match the patterns
  3. Add vibeping.track('event_name', { property: 'value' }) calls at the right points
  4. Create a vibeping-funnels.json file with your funnel and goal definitions

Let the AI do its thing. Review the changes it makes to your code โ€” make sure the tracking calls are in the right places and the event names make sense.

5. Copy the JSON output

Open the vibeping-funnels.json file your AI tool created. Copy its entire contents.

The file looks something like this:

{
  "version": 1,
  "funnels": [
    {
      "name": "Signup Flow",
      "description": "Tracks users from landing page through completed signup",
      "steps": [
        {
          "label": "Landing Page",
          "match": { "event": "page_viewed", "filters": { "path": "/" } }
        },
        {
          "label": "Signup Started",
          "match": { "event": "signup_started" }
        },
        {
          "label": "Signup Completed",
          "match": { "event": "signup_completed" }
        }
      ]
    }
  ],
  "goals": [
    {
      "name": "Signup Conversion",
      "description": "Percentage of visitors who complete signup",
      "match": { "event": "signup_completed" },
      "target_percent": 15,
      "baseline": { "event": "page_viewed" }
    }
  ]
}

6. Paste into VibePing import wizard

Back in the VibePing wizard, click Next to reach the JSON paste step. Paste the JSON into the text area and click Validate.

VibePing checks the JSON for errors:

  • Are event names valid snake_case?
  • Does each funnel have at least 2 steps?
  • Are filter values the right types?

If there are validation errors, you'll see exactly what's wrong and where. Fix the JSON and try again.

7. Preview and confirm

Once validation passes, you'll see a preview of all the funnels and goals that will be created. Review them:

  • Do the funnel names make sense?
  • Are the steps in the right order?
  • Do the goal targets seem reasonable?

Click Import to create everything. Your funnels are now live and will start collecting data as soon as users trigger the matching events.

Understanding the funnel visualization

Once your funnels have data, click any funnel to see its detail view. Here's what you're looking at:

Summary cards

Four numbers at the top:

  • Total Sessions โ€” How many user sessions entered the funnel (matched the first step)
  • Steps โ€” Number of steps in the funnel
  • Completed โ€” How many sessions made it to the last step
  • Overall Conversion โ€” Percentage that completed the entire funnel (completed รท total)

Step-by-step drop-off chart

A horizontal bar chart showing each step. The first step is always 100% width. Each subsequent step shrinks based on how many users made it there.

For each step you can see:

  • Count โ€” Absolute number of sessions that reached this step
  • % of total โ€” Conversion rate from the very first step
  • Drop badge โ€” How much dropped off compared to the previous step

Color coding:

  • ๐ŸŸข Green (66%+ conversion) โ€” Healthy, most users continue
  • ๐ŸŸก Yellow (33โ€“66% conversion) โ€” Worth investigating
  • ๐Ÿ”ด Red (below 33% conversion) โ€” Something is broken or confusing here

Step conversions table

A table with the exact numbers:

ColumnWhat it means
CountSessions that reached this step
From Previous% of users who came from the step right before
From Start% of users relative to the first step
Drop-off% that left between this step and the previous one

Period selector

Toggle between 7 days, 30 days, and 90 days to see how your funnel performs over different time windows. Use 7 days to see recent changes. Use 90 days for a bigger-picture view.

Goals

Goals are simpler than funnels. A goal tracks a single event and measures what percentage of users complete it.

Each goal has:

  • Name โ€” What you're measuring (e.g., "Signup Conversion")
  • Match event โ€” The event that counts as a conversion (e.g., signup_completed)
  • Baseline event (optional) โ€” The starting point to measure against (e.g., page_viewed). Without a baseline, the conversion rate is calculated against total sessions.
  • Target percent (optional) โ€” Your goal. Set this to track whether you're hitting your numbers.

Setting baselines and targets

Baselines answer the question "out of what?" If your goal is "Signup Conversion" and your baseline event is page_viewed, then VibePing calculates: signups รท page views = conversion rate.

Pick a baseline that represents the starting population. For signup conversion, that's usually your landing page view or homepage visit.

Targets are the number you're aiming for. Some examples:

  • SaaS signup: 5โ€“15% is typical
  • Free trial to paid: 2โ€“5% is common
  • E-commerce cart to purchase: 30โ€“60% is healthy

Start without a target. Run for a week or two to establish your baseline numbers. Then set a target slightly above your current rate and work toward it.

JSON schema reference

The import JSON must follow this exact structure:

{
  version: 1,                    // Always 1
  funnels: FunnelDefinition[],   // Array of funnels (can be empty)
  goals: GoalDefinition[]        // Array of goals (can be empty)
}

At least one funnel or one goal is required.

FunnelDefinition

{
  name: string,           // 1โ€“100 characters
  description?: string,   // Optional, max 500 characters
  steps: FunnelStep[]     // 2โ€“20 steps, in order
}

FunnelStep

{
  label: string,              // 1โ€“120 characters โ€” the display name
  match: {
    event: string,            // snake_case event name, 1โ€“100 chars
    filters?: {               // Optional key-value pairs
      [key: string]: string | number | boolean
    }
  },
  timeout_seconds?: number    // Optional, 1โ€“86400 (24 hours max)
}

The timeout_seconds field sets the maximum time between the previous step and this step. If a user takes longer, they're considered dropped off. Leave it out if you don't need time-based constraints.

GoalDefinition

{
  name: string,              // 1โ€“100 characters
  description?: string,      // Optional, max 500 characters
  match: {
    event: string,           // The conversion event (snake_case)
    filters?: {
      [key: string]: string | number | boolean
    }
  },
  target_percent?: number,   // 0โ€“100, your target conversion rate
  baseline?: {               // Optional starting-point event
    event: string,
    filters?: {
      [key: string]: string | number | boolean
    }
  }
}

Validation rules

  • Event names must be snake_case โ€” lowercase letters, numbers, and underscores only. Must start with a letter. Examples: signup_started, checkout_completed, page_viewed.
  • Filter values must be strings, numbers, or booleans. No arrays or nested objects.
  • Each funnel needs 2โ€“20 steps.
  • Maximum 20 funnels and 50 goals per import.
  • The JSON must include "version": 1 at the top level.

Full example

{
  "version": 1,
  "funnels": [
    {
      "name": "Onboarding Flow",
      "description": "New user signup through first project creation",
      "steps": [
        {
          "label": "Visited Signup Page",
          "match": { "event": "page_viewed", "filters": { "path": "/signup" } }
        },
        {
          "label": "Submitted Signup Form",
          "match": { "event": "signup_submitted" }
        },
        {
          "label": "Verified Email",
          "match": { "event": "email_verified" }
        },
        {
          "label": "Created First Project",
          "match": { "event": "project_created", "filters": { "is_first": true } }
        }
      ]
    },
    {
      "name": "Upgrade Flow",
      "description": "Free users upgrading to paid",
      "steps": [
        {
          "label": "Viewed Pricing",
          "match": { "event": "pricing_page_viewed" }
        },
        {
          "label": "Selected Plan",
          "match": { "event": "plan_selected" }
        },
        {
          "label": "Completed Payment",
          "match": { "event": "payment_completed" },
          "timeout_seconds": 1800
        }
      ]
    }
  ],
  "goals": [
    {
      "name": "Signup Completion",
      "description": "Visitors who complete the full signup flow",
      "match": { "event": "email_verified" },
      "target_percent": 12,
      "baseline": { "event": "page_viewed", "filters": { "path": "/signup" } }
    },
    {
      "name": "Upgrade Rate",
      "description": "Free users who upgrade to paid",
      "match": { "event": "payment_completed" },
      "target_percent": 4
    }
  ]
}

Tips for good funnel design

Keep funnels short and focused

3โ€“5 steps is the sweet spot. A 15-step funnel is hard to read and hard to act on. If your flow has many steps, break it into multiple funnels that cover different stages.

For example, instead of one giant "Signup โ†’ First Purchase" funnel with 12 steps, create:

  • Signup Funnel (4 steps): Landing โ†’ Signup โ†’ Verify โ†’ Dashboard
  • Activation Funnel (3 steps): Dashboard โ†’ Feature Used โ†’ Feature Used Again
  • Purchase Funnel (4 steps): Pricing โ†’ Plan Selected โ†’ Checkout โ†’ Payment

Name events clearly

Good event names describe what happened, not where it happened:

  • โœ… signup_completed, item_added_to_cart, checkout_started
  • โŒ button_clicked, form_submitted, page_2

Don't put dynamic values in event names

This is the most common mistake. Never do this:

// โŒ Bad โ€” creates thousands of unique event names
vibeping.track(`product_${productId}_viewed`)
 
// โœ… Good โ€” one event name, product ID as a property
vibeping.track('product_viewed', { product_id: productId })

Use filters for variants

If you want separate funnels for different user segments, use the same event names with filters:

{
  "label": "Viewed Pricing",
  "match": {
    "event": "pricing_page_viewed",
    "filters": { "plan_type": "enterprise" }
  }
}

Track failures, not just successes

Add events for errors and failures too. A funnel like:

Checkout Started โ†’ Payment Submitted โ†’ Payment Failed

...tells you how often payments fail. That's just as useful as knowing how often they succeed.

When to create multiple funnels

Create separate funnels when:

  • You have distinct user journeys (new vs. returning users, buyer vs. seller)
  • You want to compare different paths to the same outcome (organic signup vs. invite signup)
  • Your flow has natural breakpoints where users might come back later (signup today, activate next week)

Don't create separate funnels for:

  • Minor UI variations (these are better handled with filters)
  • Every single page in your app (that's not a funnel, that's a sitemap)

Start with 2โ€“3 funnels

You don't need to track everything on day one. Start with:

  1. Your main conversion funnel (the thing your app exists to do)
  2. Your onboarding funnel (how new users get started)
  3. Optionally, a monetization funnel (if you charge money)

Add more once you understand the basics.

Editing funnels

Simple edits

You can rename funnel steps, update descriptions, or reorder steps directly through the API. The funnel detail page shows the current configuration at the bottom.

Structural changes

If you need to add new steps, change which events are tracked, or redesign the funnel entirely:

  1. Go back to /funnels and click + Add Funnels
  2. Run through the wizard again with the updated prompt
  3. Delete the old funnel once the new one is working

Re-running the prompt is often easier than manually editing the JSON, especially if you've also changed the tracking calls in your code.

Deleting funnels and goals

Hover over any funnel or goal in the list view to reveal the delete button. Deleting a funnel removes the definition โ€” it doesn't remove the tracking events from your code. Historical data for deleted funnels is not recoverable.

A note on re-running prompts

If you re-run the setup prompt in your AI coding tool, it may add duplicate vibeping.track() calls to your code. Check the diff before accepting changes. The JSON import is safe to run multiple times โ€” it creates new funnels, it doesn't overwrite existing ones.