Skip to content

Tulo Engage BI

Churn model

The base for the churn model relies on the subscription and subscription period models to build reliable data every night.

Churn data is collected every night for different aspects of the subscription stock, making it possible to filter and slice data in various ways. On mondays daily statistics are aggregated into weekly statistics and on 1:st day of month monthly statistics data is aggregated.

Churn calculations

Calculating a churn rate is made by dividing the number of deactivated subscriptions with the number of active subscriptions at the start of the period being inspected.

    (number of deactivations in period / number of active subscriptions at start of period) * 100 = churn rate in percent

When calculating churn we summarize all deactivation categories except deactivated_campaign_transformation, since those are made internally by Payway as a part of transforming a subscription from campaign to a standard subscription.

Daily data

Table: engage_bi.pw_churn_data_daily

column type comments
working_date date Date statistics was collected
organisation_id string The organisation that owns the subscription
product_code string Product code for the subscription.
product_type string Type of product. Codes and values.
product_title_code string Title code for the product
order_category string Category of order. Codes and values.
order_type string Type of order, "normal", "no_order", or "voucher" if order was created through redeeming a voucher.
order_period_type string Period type on current order. "year", "month", "week" or "day".
order_period_length int Length of period
order_payment_method string Payment method used when purchasing order. Codes and values.
campaign_product_code string The product code the campaign is based upon if order is campaign.
subscription_type string Indicates if the subscription is "recurring", "limited" or "free". Codes and values.
subscription_category string Indicates if the subscription is an actual "subscription" or a "lead". Codes and values.
subscription_business_model string Indicates if the subscription belongs to a company ("b2b") or a private person ("b2c"). Determined by the package property "Company package" which is accessible from "Field configuration" on a package.
customer_age int Age of customer if known.
customer_gender string Gender of customer if known, "M" = Male or "F" = Female, "?" if unknown.
product_tags string Comma separated list of tags for the subscription.
active_subscriptions int Number of active subscriptions current working date.
deactivated_customer_cancel int Number of deactivations initiated by customer
deactivated_customer_passive_payment int Number of deactivations due to failure to pay
deactivated_subscription_expired int Number of deactivations due to expiration of time limited subscription
deactivated_subscription_change int Number of deactivations due to change of subscription
deactivated_subscription_downgrade int Number of deactivations due to downgrade of subscription
deactivated_subscription_upgrade int Number of deactivations due to upgrade of subscription
deactivated_subscription_extension int Number of deactivations due to extension of subscription
deactivated_campaign_transformation int Number of deactivations due to campaign transformation (not included in churn calculations)
deactivated_system int Number of deactivations due to other reasons than mentioned above, could be internal or customer ordered jobs for example.
added_subscriptions int Number of subscriptions added this working date.
shared_subscriptions int Number of shared subscriptions.

Weekly data

Table: engage_bi.pw_churn_data_weekly

column type comments
week_start_date date Start date of week
week_end_date date End date of week
week_no date Week number
organisation_id string The organisation that owns the subscription
product_code string Product code for the subscription.
product_type string Type of product. Codes and values.
product_title_code string Title code for the product
order_category string Category of order. Codes and values.
order_type string Type of order, "normal", "no_order", or "voucher" if order was created through redeeming a voucher.
order_period_type string Period type on current order. "year", "month", "week" or "day".
order_period_length int Length of period
order_payment_method string Payment method used when purchasing order. Codes and values.
campaign_product_code string The product code the campaign is based upon if order is campaign.
subscription_type string Indicates if the subscription is "recurring", "limited" or "free". Codes and values.
subscription_category string Indicates if the subscription is an actual "subscription" or a "lead". Codes and values.
subscription_business_model string Indicates if the subscription belongs to a company ("b2b") or a private person ("b2c"). Determined by the package property "Company package" which is accessible from "Field configuration" on a package.
customer_age int Age of customer if known.
customer_gender string Gender of customer if known, "M" = Male or "F" = Female, "?" if unknown.
product_tags string Comma separated list of tags for the subscription.
active_subscriptions_start int Number of active subscriptions at start of week.
active_shared_start int Number of shared subscriptions at start of week.
active_subscriptions_end int Number of active subscriptions at end of week.
active_shared_end int Number of shared subscriptions at end of week.
deactivated_customer_cancel int Number of deactivations initiated by customer
deactivated_customer_passive_payment int Number of deactivations due to failure to pay
deactivated_subscription_expired int Number of deactivations due to expiration of time limited subscription
deactivated_subscription_change int Number of deactivations due to change of subscription
deactivated_subscription_downgrade int Number of deactivations due to downgrade of subscription
deactivated_subscription_upgrade int Number of deactivations due to upgrade of subscription
deactivated_subscription_extension int Number of deactivations due to extension of subscription
deactivated_campaign_transformation int Number of deactivations due to campaign transformation (not included in churn calculations)
deactivated_system int Number of deactivations due to other reasons than mentioned above, could be internal or customer ordered jobs for example.
added_subscriptions int Number of subscriptions added this week.

Monthly data

Table: engage_bi.pw_churn_data_monthly

column type comments
month_start_date date Start date of month
month_end_date date End date of month
organisation_id string The organisation that owns the subscription
product_code string Product code for the subscription.
product_type string Type of product. Codes and values.
product_title_code string Title code for the product
order_category string Category of order. Codes and values.
order_type string Type of order, "normal", "no_order", or "voucher" if order was created through redeeming a voucher.
order_period_type string Period type on current order. "year", "month", "week" or "day".
order_period_length int Length of period
order_payment_method string Payment method used when purchasing order. Codes and values.
campaign_product_code string The product code the campaign is based upon if order is campaign.
subscription_type string Indicates if the subscription is "recurring", "limited" or "free". Codes and values.
subscription_category string Indicates if the subscription is an actual "subscription" or a "lead". Codes and values.
subscription_business_model string Indicates if the subscription belongs to a company ("b2b") or a private person ("b2c"). Determined by the package property "Company package" which is accessible from "Field configuration" on a package.
customer_age int Age of customer if known.
customer_gender string Gender of customer if known, "M" = Male or "F" = Female, "?" if unknown.
product_tags string Comma separated list of tags for the subscription.
active_subscriptions_start int Number of active subscriptions at start of month.
active_shared_start int Number of shared subscriptions at start of month.
active_subscriptions_end int Number of active subscriptions at end of month.
active_shared_end int Number of shared subscriptions at end of month.
deactivated_customer_cancel int Number of deactivations initiated by customer
deactivated_customer_passive_payment int Number of deactivations due to failure to pay
deactivated_subscription_expired int Number of deactivations due to expiration of time limited subscription
deactivated_subscription_change int Number of deactivations due to change of subscription
deactivated_subscription_downgrade int Number of deactivations due to downgrade of subscription
deactivated_subscription_upgrade int Number of deactivations due to upgrade of subscription
deactivated_subscription_extension int Number of deactivations due to extension of subscription
deactivated_campaign_transformation int Number of deactivations due to campaign transformation (not included in churn calculations)
deactivated_system int Number of deactivations due to other reasons than mentioned above, could be internal or customer ordered jobs for example.
added_subscriptions int Number of subscriptions added this working date.

Added subscriptions

A subscription is classified as added a specific day if it has a subscription period with a start date matching the specific day. This can include subscriptions that have been purchased with a future start date, then the start date will be the activation date of the subscription. It will also include a subscription that previously have been deactivated due to failure to pay in time, but later have been reactivated at the specific day due to a late payment.

Added and deactivated

As a step in the nightly aggregation of churn data, added and deactivated subscriptions are also collected into separate tables so it is easy to find which subscriptions that have been added or deactivated a specific day.

Added

Table: engage_bi.pw_subscriptions_added_daily

column type comments
working_date date Date statistics was collected
organisation_id string The organisation that owns the subscription
subscription_id string The subscription added
created_from string Indicates how the subscription was created, from "migration" or a "purchase" for example. Codes and values.

Deactivated

Table: engage_bi.pw_subscriptions_deactivated_daily

column type comments
working_date date Date statistics was collected
organisation_id string The organisation that owns the subscription
subscription_id string The subscription added
deactivation_reason string The reason for deactivation of the subscription if it is deactivated. Codes and values.

Sample queries

Active subscriptions a specific day

Find number of active "digital only" subscriptions for the first day of the year which are actually paid. Meaning we do not want to include free subscriptions and also not any campaigns that have started with a totally zero cost period, also check product type to filter digital only products.

SELECT working_date, 
       SUM(active_subscriptions)
FROM engage_bi.pw_churn_data_daily
WHERE working_date = '2025-01-01'       
AND subscription_type != 'free'
AND order_category != 'zero_campaign'
AND product_type = 'digital_only'
GROUP BY working_date;

Active subscriptions weekly

Same as above, but get weekly overview including netgain.

SELECT week_start_date,
       week_end_date, 
       SUM(active_subscriptions_start) AS active_start,
       SUM(active_subscriptions_end) AS active_end,
       (active_end - active_start) AS netgain
FROM engage_bi.pw_churn_data_weekly
WHERE subscription_type != 'free'
AND order_category != 'zero_campaign'
AND product_type = 'digital_only'
AND week_start_date > '2025-01-01'
GROUP BY week_start_date, week_end_date
ORDER BY week_start_date DESC;

Active subscriptions monthly

Same as above, but get monthly overview including netgain.

SELECT month_start_date,
       month_end_date, 
       SUM(active_subscriptions_start) AS active_start,
       SUM(active_subscriptions_end) AS active_end,
       (active_end - active_start) AS netgain
FROM engage_bi.pw_churn_data_monthly
WHERE subscription_type != 'free'
AND order_category != 'zero_campaign'
AND product_type = 'digital_only'
AND month_start_date = '2025-01-01'
GROUP BY month_start_date, month_end_date
ORDER BY month_start_date DESC;

Active subscriptions and churn rate monthly

Same as above, but also add churn rate

SELECT month_start_date,
       month_end_date, 
       SUM(active_subscriptions_start) AS active_start,
       SUM(active_subscriptions_end) AS active_end,
       (active_end - active_start) AS netgain,
       SUM(deactivated_customer_cancel
           +deactivated_customer_passive_payment
           +deactivated_subscription_change
           +deactivated_subscription_expired
           +deactivated_subscription_downgrade
           +deactivated_subscription_upgrade
           +deactivated_subscription_extension           
           +deactivated_system) AS deactivated,
       ROUND((deactivated / active_start::FLOAT)*100, 2) AS churn_rate
FROM engage_bi.pw_churn_data_monthly
WHERE subscription_type != 'free'
AND order_category != 'zero_campaign'
AND product_type = 'digital_only'
AND month_start_date = '2025-01-01'
GROUP BY month_start_date, month_end_date
ORDER BY month_start_date DESC;