Customer Value Drivers

Decomposes changes in average customer value into base, acquisition, and churn-driven effects.

Purpose

Provide a driver-based view of customer value evolution, attributing period-over-period changes in average customer value to underlying customer dynamics.

This model is designed as an explanatory reporting layer, enabling:

  • Attribution of ARPA changes to customer mix effects
  • Separation of acquisition, retention, and churn impacts
  • Clear reconciliation between customer value levels and movements

It shifts the analysis from what changed to what caused the change.

Business Logic

  • Start from Customer Value
  • Join with Customer Count View
  • Compute period-over-period deltas using LAG
  • Attribute customer value changes proportionally based on customer mix:
    • Existing customer base
    • New customers
    • Churned customers
  • Ensure driver components reconcile to total customer value change
  • Exclude the first period where lagged values are unavailable

Output Contract

Definitions

ColumnDescription
dateDate of the snapshot (YYYY-MM-DD)
value_typeIndicator such as actual, budget
current_baseCustomer value change driven by existing customers
new_customersCustomer value change driven by newly acquired customers
churnCustomer value change driven by churn dynamics (negative impact)
customer_value_deltaTotal change in average customer value vs prior period

Sample & Implementation

Drivers of period-over-period changes in average customer value.
datevalue_typecurrent_basenew_customerschurncustomer_value_delta
2025-02-01budget73.9779-6.92761.500973.9770
2025-03-01budget72.86670.0011-0.000272.8668
2025-04-01budget71.78840.0006-0.000171.7907
2025-05-01budget70.74153.3762-7.315170.7394
2025-06-01budget69.7247-0.00100.000269.7261
2025-07-01budget68.75750.0010-0.000268.7592
2025-08-01budget67.81670.0010-0.000267.8164
2025-09-01budget66.90140.0007-0.000166.9011
2025-10-01budget66.0104-0.00038.391966.0120
2025-11-01budget65.1428-0.00050.000165.1409
{{config(materialized='view')}}


with customer_value as (
    select * from {{ ref('customer_value') }}
),

customer_count_view as (
    select * from {{ref('customer_count_view')}}
),

calculated_values as (
    select
        cv.date,
        cv.value_type,
        (cv.current_base - LAG(cv.total_customer_value) OVER (PARTITION BY cv.value_type ORDER BY cv.date)) * (ccv.current_base / ccv.ending_balance) as current_base,
        (cv.new_customers - LAG(cv.total_customer_value) OVER (PARTITION BY cv.value_type ORDER BY cv.date)) * (ccv.new_customers / ccv.ending_balance) as new_customers,
        -(cv.churn - LAG(cv.total_customer_value) OVER (PARTITION BY cv.value_type ORDER BY cv.date)) * (ccv.churn / ccv.ending_balance) as churn,
        (cv.total_customer_value - LAG(cv.total_customer_value) OVER (PARTITION BY cv.value_type ORDER BY cv.date) ) as customer_value_delta
    from customer_value cv
    left join customer_count_view ccv on cv.date = ccv.date and cv.value_type = ccv.value_type
)

select *
from calculated_values
where current_base IS NOT NULL

Dependencies

On this page

Star us on GitHub

If you enjoy this content and find it useful, give us a star on GitHub to show your support and stay updated with our latest improvements.