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.