Skip to content
← Back to Functions
Code

Revenue Cohort Builder

Groups purchases or subscriptions into cohorts and summarizes revenue by period.

Function signature

ogBuildRevenueCohorts(orders = array(), options = array())

Categories

  • Analytics and Reports

Parameters

ordersOrder rows with cohort/date and revenue fields.optionsOptional keys: cohort_date_key, revenue_key, period_date_key. Recognized keys: `cohort_date_key`, `period_date_key`, `revenue_key`.

Return value

Short public-safe status message.

  • cohorts
  • skipped

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.
 */

/**
 * Groups purchases or subscriptions into cohorts and summarizes revenue by period.
 *
 * @param array $orders Order rows with cohort/date and revenue fields.
 * @param array $options Optional keys: cohort_date_key, revenue_key, period_date_key.
 * @return array Cohort table keyed by cohort month and activity month.
 */
function ogBuildRevenueCohorts($orders = array(), $options = array()) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	if (!is_array($orders)) {
		$result['message'] = 'Orders must be an array.';
		return $result;
	}

	if (!is_array($options)) {
		$options = array();
	}

	$cohort_date_key = 'cohort_date';
	$period_date_key = 'order_date';
	$revenue_key = 'revenue_minor_units';
	if (!empty($options['cohort_date_key'])) {
		$cohort_date_key = (string)$options['cohort_date_key'];
	}
	if (!empty($options['period_date_key'])) {
		$period_date_key = (string)$options['period_date_key'];
	}
	if (!empty($options['revenue_key'])) {
		$revenue_key = (string)$options['revenue_key'];
	}

	$cohorts = array();
	$skipped = 0;
	foreach ($orders as $order) {
		if (!is_array($order)) {
			$skipped++;
			continue;
		}
		if (empty($order[$cohort_date_key]) || empty($order[$period_date_key]) || !isset($order[$revenue_key])) {
			$skipped++;
			continue;
		}

		$cohort_time = strtotime((string)$order[$cohort_date_key]);
		$period_time = strtotime((string)$order[$period_date_key]);
		if ($cohort_time === false || $period_time === false || !is_numeric($order[$revenue_key])) {
			$skipped++;
			continue;
		}

		$cohort = date('Y-m', $cohort_time);
		$period = date('Y-m', $period_time);
		if (empty($cohorts[$cohort])) {
			$cohorts[$cohort] = array();
		}
		if (empty($cohorts[$cohort][$period])) {
			$cohorts[$cohort][$period] = array('orders' => 0, 'revenue_minor_units' => 0);
		}
		$cohorts[$cohort][$period]['orders']++;
		$cohorts[$cohort][$period]['revenue_minor_units'] += (int)$order[$revenue_key];
	}

	$result['success'] = true;
	$result['message'] = 'Revenue cohorts built.';
	$result['data'] = array(
		'cohorts' => $cohorts,
		'skipped' => $skipped
	);

	return $result;
}