Skip to main content

Funnel Metrics

The funnel endpoint provides a conversion funnel for any form, showing how users progress from viewing the form to completing a submission.

Funnel Stages

View -> Start -> Submit
                  \-> Abandon
                  \-> Spam
Metric Description
views Form impressions: once per rendered form instance when any part enters the viewport or a field receives focus
starts First focus within each rendered form instance, counted once
submissions Successful form submissions
abandonments Users who started but left without submitting
spam Submissions flagged as spam

Derived Rates

The API calculates four conversion rates automatically:

Rate Formula What It Tells You
start_rate min(100, (starts / views) * 100) How compelling your form looks
completion_rate (submissions / starts) * 100 How easy your form is to complete
abandonment_rate (abandonments / starts) * 100 Where friction exists
spam_rate (spam / (submissions + spam)) * 100 Spam as a percentage of all attempts

REST API

Get Funnel Data

GET /wp-json/cf/v1/analytics/{form_id}/funnel

Parameters:

Parameter Type Description
date_from string Start date (Y-m-d). Optional.
date_to string End date (Y-m-d). Optional.

Response:

{
    "views": 1500,
    "starts": 450,
    "submissions": 180,
    "abandonments": 270,
    "spam": 12,
    "start_rate": 30.0,
    "completion_rate": 40.0,
    "abandonment_rate": 60.0,
    "spam_rate": 6.3
}

Get Daily Stats

For charting funnel data over time:

GET /wp-json/cf/v1/analytics/{form_id}/daily

Required parameters: date_from, date_to

Response:

[
    { "date": "2026-04-01", "event_type": "view", "count": "52" },
    { "date": "2026-04-01", "event_type": "start", "count": "15" },
    { "date": "2026-04-01", "event_type": "submit", "count": "6" },
    { "date": "2026-04-02", "event_type": "view", "count": "48" },
    { "date": "2026-04-02", "event_type": "submit", "count": "8" }
]

PHP Usage

use Core_Forms\Analytics\Dashboard;

// Get funnel for a specific form
$funnel = Dashboard::get_funnel( $form_id );

// Get funnel for a date range
$funnel = Dashboard::get_funnel( $form_id, '2026-01-01', '2026-03-31' );

// Get daily breakdowns
$daily = Dashboard::get_daily_stats( $form_id, '2026-04-01', '2026-04-07' );

Event Recording

Events are recorded from two sources:

Client-Side (AJAX)

The JavaScript tracker sends view, start, abandon, and field_interaction events via AJAX:

POST /wp-admin/admin-ajax.php
action=cf_track_event
form_id=123
event_type=view
page_url=https://example.com/contact

Server-Side (Hooks)

Submit and spam events are recorded automatically via hooks:

// On successful submission
add_action( 'cf_form_success', [ $tracker, 'on_submit' ], 100, 2 );

// On spam detection
add_action( 'cf_form_response', [ $tracker, 'on_spam_check' ], 100, 3 );

Interpreting the Data

  • start_rate < 10% with 50+ views: Form may not be visible or looks intimidating. See Recommendations.
  • completion_rate < 30% with 20+ starts: Form may be too long. Consider reducing fields or using multi-step.
  • abandonment_rate > 60%: High friction. Check Field Drop-off to find problem fields.
  • spam_rate > 30%: Enable additional spam protection. See Spam Protection.

Related

Counting and missing views

Views and starts are counted once per rendered form instance, not once per browser session. Reloading a page permits one new view and one new start. Focusing a field also records its view if the visibility observer has not run yet. Tall forms only need to partially enter the viewport.

The raw counts and daily activity are preserved. Older data, blocked requests, or date boundaries can leave more starts than recorded views. In that case start_rate_capped is true, the start rate is capped at 100%, and the dashboard labels it as capped with missing views. With zero views, the API returns a rate of 0 and the dashboard says the rate is unavailable. These figures are event ratios, not unique-person conversion rates; submissions and abandonments retain their existing event counts.