Funnel Conversion Calculator
Calculates step-by-step conversion rates and drop-off percentages.
Function signature
ogCalculateFunnelConversion(steps = array(), options = array())
Categories
- Analytics and Reports
Parameters
stepsOrdered counts or rows with name/count keys.optionsOptional keys: name_key, count_key. Recognized keys: `count_key`, `name_key`.Return value
Short public-safe status message.
- steps
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Calculates step-by-step conversion rates and drop-off percentages.
*
* @param array $steps Ordered counts or rows with name/count keys.
* @param array $options Optional keys: name_key, count_key.
* @return array Funnel report with conversion and drop-off rows.
*/
function ogCalculateFunnelConversion($steps = array(), $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($steps)) {
$result['message'] = 'Steps must be an array.';
return $result;
}
if (!is_array($options)) {
$options = array();
}
$name_key = 'name';
$count_key = 'count';
if (!empty($options['name_key'])) {
$name_key = (string)$options['name_key'];
}
if (!empty($options['count_key'])) {
$count_key = (string)$options['count_key'];
}
$normalized = array();
foreach ($steps as $index => $step) {
$name = 'Step ' . ($index + 1);
$count = null;
if (is_array($step)) {
if (!empty($step[$name_key])) {
$name = trim((string)$step[$name_key]);
}
if (isset($step[$count_key]) && is_numeric($step[$count_key])) {
$count = (float)$step[$count_key];
}
} else {
if (is_numeric($step)) {
$count = (float)$step;
}
}
if ($count !== null && $count >= 0) {
$normalized[] = array('name' => $name, 'count' => $count);
}
}
if (count($normalized) < 2) {
$result['message'] = 'At least two funnel steps are required.';
return $result;
}
$first_count = $normalized[0]['count'];
$rows = array();
$previous_count = 0;
foreach ($normalized as $index => $step) {
$step_conversion = 100;
$dropoff = 0;
if ($index > 0) {
if ($previous_count > 0) {
$step_conversion = ($step['count'] / $previous_count) * 100;
$dropoff = (($previous_count - $step['count']) / $previous_count) * 100;
} else {
$step_conversion = 0;
$dropoff = 0;
}
}
$total_conversion = 0;
if ($first_count > 0) {
$total_conversion = ($step['count'] / $first_count) * 100;
}
$rows[] = array(
'name' => $step['name'],
'count' => $step['count'],
'step_conversion_percent' => $step_conversion,
'total_conversion_percent' => $total_conversion,
'dropoff_percent' => $dropoff
);
$previous_count = $step['count'];
}
$result['success'] = true;
$result['message'] = 'Funnel conversion calculated.';
$result['data'] = array('steps' => $rows);
return $result;
}