Subscription Growth Analysis
Produces a same-period MoM subscription health report covering MRR, churn,
net growth, and product/country mix — both windows spanning the same number of
days for a like-for-like comparison.
Step 0 — Setup
Org ID: Retrieve via list_organizations if not already known. Ask if multiple exist.
Date windows — use the same logic as the other pillar skills:
today = current date
cm_start = first day of current month → cm_end = today
lm_start = first day of prior month → lm_end = prior month day matching today
(cap lm_end at last day of prior month if today's day > prior month's length)
State windows and offer custom dates:
"Comparing May 1–19 vs April 1–19. Want to use different dates instead?"
If called by the orchestrator, accept windows directly — don't re-prompt.
Step 1 — Fetch all data
Batch A — 10 calls in parallel
| # |
Tool |
Purpose |
Key params |
| 1 |
ZohoBilling_get_subscriptions_summary_report |
Subscription status counts — CP |
filter_by: ActivatedDate.CustomDate, from_date: <cm_start>, to_date: <cm_end> |
| 2 |
ZohoBilling_get_subscriptions_summary_report |
Subscription status counts — PP |
same, from_date: <lm_start>, to_date: <lm_end> |
| 3 |
ZohoBilling_get_mrr_report |
MRR — CP |
filter_by: ActivatedDate.CustomDate, from_date: <cm_start>, to_date: <cm_end> |
| 4 |
ZohoBilling_get_mrr_report |
MRR — PP |
same, from_date: <lm_start>, to_date: <lm_end> |
| 5 |
ZohoBilling_get_activations_report |
Activation totals — CP |
filter_by: SubscriptionDate.CustomDate, from_date: <cm_start>, to_date: <cm_end>, per_page: 100 |
| 6 |
ZohoBilling_get_activations_report |
Activation totals — PP |
same, from_date: <lm_start>, to_date: <lm_end>, per_page: 100 |
| 7 |
ZohoBilling_get_productwise_activations_report |
Activations by product — CP |
filter_by: SubscriptionDate.CustomDate, from_date: <cm_start>, to_date: <cm_end>, sort_column: total, sort_order: D, per_page: 100 |
| 8 |
ZohoBilling_get_productwise_activations_report |
Activations by product — PP |
same, from_date: <lm_start>, to_date: <lm_end>, per_page: 100 |
| 9 |
ZohoBilling_get_productwise_cancellations_report |
Cancellations by product — CP |
filter_by: CancellationDate.CustomDate, from_date: <cm_start>, to_date: <cm_end>, sort_column: total, sort_order: D, per_page: 100 |
| 10 |
ZohoBilling_get_productwise_cancellations_report |
Cancellations by product — PP |
same, from_date: <lm_start>, to_date: <lm_end>, per_page: 100 |
Batch B — 4 more calls in parallel (after Batch A)
| # |
Tool |
Purpose |
Key params |
| 11 |
ZohoBilling_get_countrywise_activations_report |
Activations by country — CP |
filter_by: SubscriptionDate.CustomDate, from_date: <cm_start>, to_date: <cm_end>, sort_column: total, sort_order: D, per_page: 100 |
| 12 |
ZohoBilling_get_countrywise_activations_report |
Activations by country — PP |
same, from_date: <lm_start>, to_date: <lm_end>, per_page: 100 |
| 13 |
ZohoBilling_get_countrywise_cancellations_report |
Cancellations by country — CP |
filter_by: CancellationDate.CustomDate, from_date: <cm_start>, to_date: <cm_end>, sort_column: total, sort_order: D, per_page: 100 |
| 14 |
ZohoBilling_get_countrywise_cancellations_report |
Cancellations by country — PP |
same, from_date: <lm_start>, to_date: <lm_end>, per_page: 100 |
Paginate while has_more_page: true. Use API total fields for period-level
sums (activations, cancellations) — do not aggregate rows when pagination may
truncate.
Step 2 — Compute subscription metrics
2a. Active subscribers and MRR
| Metric |
Formula |
| Active subs end-of-CP |
live count from call #1 |
| Active subs end-of-PP |
live count from call #2 |
| MoM active subs Δ |
CP − PP (absolute and %) |
| MRR (CP) |
from call #3 |
| MRR (PP) |
from call #4 |
| MoM MRR Δ |
MRR_CP − MRR_PP (absolute and %) |
| ARPU (CP) |
MRR_CP / active_subs_CP |
| ARPU (PP) |
MRR_PP / active_subs_PP |
| ARPU Δ |
(ARPU_CP − ARPU_PP) / ARPU_PP × 100 |
2b. Activations and cancellations
| Metric |
Formula |
| Activations CP / PP |
API totals from calls #5 / #6 |
| Cancellations CP / PP |
API totals from productwise calls #9 / #10 summed |
| Net growth CP |
activations_CP − cancellations_CP |
| Net growth PP |
activations_PP − cancellations_PP |
| MoM activation % |
(act_CP − act_PP) / act_PP × 100 |
| MoM cancellation % |
(can_CP − can_PP) / can_PP × 100 |
| MoM net growth Δ |
net_CP − net_PP |
2c. Churn rate
monthly_churn_CP = cancellations_CP / active_subs_PP × 100
monthly_churn_PP = cancellations_PP / (active_subs at start of PP — use PP live subs)
Standard SaaS convention: denominator is start-of-period active subs (use PP's
live count as the CP denominator).
Note for dashboard: if CP is a partial month, label as "period churn rate
(N-day window)" rather than "monthly" to avoid over-stating.
2d. MRR decomposition (if available)
Call ZohoBilling_get_mrr_insights_report for CP. If it returns data, extract:
- New MRR (new activations)
- Expansion MRR (upgrades / add-ons)
- Contraction MRR (downgrades)
- Churned MRR (cancellations)
- Net MRR movement
If the report returns empty or is unavailable, skip this section — don't estimate.
2e. Product breakdown
From calls #7–10, build a per-product table for top 10 products by CP activations.
For each product:
- Activations CP and PP
- Cancellations CP and PP
- Net growth CP = act_CP − can_CP
- Net growth PP = act_PP − can_PP
- MoM net growth Δ
Compute top-product activation concentration = (product_1_act / total_act_CP) × 100.
Flag products with:
- Net negative growth in CP (cancellations > activations)
20% MoM drop in activations
- Zero PP history (new product launch in CP)
2f. Country breakdown
From calls #11–14, apply the same analysis as 2e for top 10 countries by CP total
activity (activations + cancellations).
For each country:
- Activations CP and PP
- Cancellations CP and PP
- Net growth CP and PP
- MoM net growth Δ
Compute top-country activation concentration = (country_1_act / total_act_CP) × 100.
Flag:
- Countries with net negative growth (shrinking markets)
- Countries new in CP (emerging markets — zero PP history)
- "Others" bucket if > 15% of activations (unattributed addresses)
Step 3 — Produce the analysis output
## Subscription Growth — <period_label_cm> vs <period_label_lm>
### Key Metrics
| Metric | <PP label> | <CP label> | Δ |
|---|---|---|---|
| Active subscribers | N | N | +N (+N%) |
| MRR | $X | $Y | +$Z (+N%) |
| ARPU | $X | $Y | +$Z |
| Activations | N | N | +N (+N%) |
| Cancellations | N | N | +N |
| Net growth | +N | +N | +N |
| Period churn rate | N% | N% | +Npp |
**MRR: <direction and magnitude>. Net growth: <direction and magnitude>.**
### MRR Decomposition (if available)
| Component | CP |
|---|---|
| New MRR | +$X |
| Expansion | +$X |
| Contraction | -$X |
| Churned | -$X |
| **Net MRR** | **+$X** |
### Product Performance (Top 10 by CP Activations)
| Product | Act PP | Act CP | Can CP | Net CP | MoM Net Δ |
|---|---|---|---|---|---|
...
_Top-product concentration: N% of activations from "<product name>"_
### Country Performance (Top 10 by CP Activity)
| Country | Act PP | Act CP | Can CP | Net CP | MoM Net Δ |
|---|---|---|---|---|---|
...
_Top-country concentration: N% of activations from "<country>"_
Growing: <list> Shrinking: <list>
Output contract (for orchestrator)
{
"pillar": "subscriptions",
"metrics": {
"active_subs_cp": <number>,
"active_subs_pp": <number>,
"mrr_cp": <number>,
"mrr_pp": <number>,
"mom_mrr_pct": <number>,
"activations_cp": <number>,
"activations_pp": <number>,
"cancellations_cp": <number>,
"net_growth_cp": <number>,
"net_growth_pp": <number>,
"period_churn_rate_cp_pct": <number>,
"arpu_cp": <number>,
"arpu_pp": <number>,
"top_product_concentration_pct": <number>,
"top_country_concentration_pct": <number>
},
"mrr_decomposition": {"new": ..., "expansion": ..., "contraction": ..., "churned": ..., "net": ...},
"top_products": [{"name": "...", "activations_cp": ..., "net_cp": ..., "net_pp": ...}],
"top_countries": [{"name": "...", "activations_cp": ..., "net_cp": ..., "net_pp": ...}],
"flags": ["<shrinking markets>", "<product net negative>", "<concentration risk>"]
}
Edge cases
- New org (< 1 month old): PP will be empty. Analyse CP only; note it.
- Products with zero PP data: label as "new product" — don't compute Δ%.
- Churn > 100%: impossible; if it appears, warn and skip churn scoring — denominator likely wrong.
- MRR = 0 for free plans: exclude from ARPU; count them separately as "free subscribers."
- "Others" country: include if top 10, flag as unattributed.
- MRR decomposition unavailable: skip the section entirely.
1---2name: subscription-growth-analysis3description: Analyse subscription growth by comparing two equal-length date windows — this month day 1 to today, vs the same day range in the prior month (e.g., May 1–19 vs April 1–19). Pulls Zoho Billing active subscriptions, MRR, activations, and product/country breakdowns. Surfaces MRR trajectory, churn rate, net subscriber growth, and geographic/product mix. Use when the user asks about subscriber growth, MRR trends, churn, activations by product or market, geographic expansion, or any subscription-level performance question.4---56# Subscription Growth Analysis78Produces a **same-period MoM subscription health report** covering MRR, churn,9net growth, and product/country mix — both windows spanning the same number of10days for a like-for-like comparison.1112---1314## Step 0 — Setup1516**Org ID**: Retrieve via `list_organizations` if not already known. Ask if multiple exist.1718**Date windows** — use the same logic as the other pillar skills:1920```21today = current date22cm_start = first day of current month → cm_end = today23lm_start = first day of prior month → lm_end = prior month day matching today24 (cap lm_end at last day of prior month if today's day > prior month's length)25```2627State windows and offer custom dates:28> "Comparing **May 1–19** vs **April 1–19**. Want to use different dates instead?"2930If called by the orchestrator, accept windows directly — don't re-prompt.3132---3334## Step 1 — Fetch all data3536### Batch A — 10 calls in parallel3738| # | Tool | Purpose | Key params |39|---|------|---------|------------|40| 1 | `ZohoBilling_get_subscriptions_summary_report` | Subscription status counts — CP | `filter_by: ActivatedDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>` |41| 2 | `ZohoBilling_get_subscriptions_summary_report` | Subscription status counts — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>` |42| 3 | `ZohoBilling_get_mrr_report` | MRR — CP | `filter_by: ActivatedDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>` |43| 4 | `ZohoBilling_get_mrr_report` | MRR — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>` |44| 5 | `ZohoBilling_get_activations_report` | Activation totals — CP | `filter_by: SubscriptionDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>`, `per_page: 100` |45| 6 | `ZohoBilling_get_activations_report` | Activation totals — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>`, `per_page: 100` |46| 7 | `ZohoBilling_get_productwise_activations_report` | Activations by product — CP | `filter_by: SubscriptionDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>`, `sort_column: total`, `sort_order: D`, `per_page: 100` |47| 8 | `ZohoBilling_get_productwise_activations_report` | Activations by product — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>`, `per_page: 100` |48| 9 | `ZohoBilling_get_productwise_cancellations_report` | Cancellations by product — CP | `filter_by: CancellationDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>`, `sort_column: total`, `sort_order: D`, `per_page: 100` |49| 10 | `ZohoBilling_get_productwise_cancellations_report` | Cancellations by product — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>`, `per_page: 100` |5051### Batch B — 4 more calls in parallel (after Batch A)5253| # | Tool | Purpose | Key params |54|---|------|---------|------------|55| 11 | `ZohoBilling_get_countrywise_activations_report` | Activations by country — CP | `filter_by: SubscriptionDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>`, `sort_column: total`, `sort_order: D`, `per_page: 100` |56| 12 | `ZohoBilling_get_countrywise_activations_report` | Activations by country — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>`, `per_page: 100` |57| 13 | `ZohoBilling_get_countrywise_cancellations_report` | Cancellations by country — CP | `filter_by: CancellationDate.CustomDate`, `from_date: <cm_start>`, `to_date: <cm_end>`, `sort_column: total`, `sort_order: D`, `per_page: 100` |58| 14 | `ZohoBilling_get_countrywise_cancellations_report` | Cancellations by country — PP | same, `from_date: <lm_start>`, `to_date: <lm_end>`, `per_page: 100` |5960Paginate while `has_more_page: true`. Use API `total` fields for period-level61sums (activations, cancellations) — do not aggregate rows when pagination may62truncate.6364---6566## Step 2 — Compute subscription metrics6768### 2a. Active subscribers and MRR6970| Metric | Formula |71|---|---|72| Active subs end-of-CP | `live` count from call #1 |73| Active subs end-of-PP | `live` count from call #2 |74| MoM active subs Δ | CP − PP (absolute and %) |75| MRR (CP) | from call #3 |76| MRR (PP) | from call #4 |77| MoM MRR Δ | MRR_CP − MRR_PP (absolute and %) |78| ARPU (CP) | MRR_CP / active_subs_CP |79| ARPU (PP) | MRR_PP / active_subs_PP |80| ARPU Δ | (ARPU_CP − ARPU_PP) / ARPU_PP × 100 |8182### 2b. Activations and cancellations8384| Metric | Formula |85|---|---|86| Activations CP / PP | API totals from calls #5 / #6 |87| Cancellations CP / PP | API totals from productwise calls #9 / #10 summed |88| Net growth CP | activations_CP − cancellations_CP |89| Net growth PP | activations_PP − cancellations_PP |90| MoM activation % | (act_CP − act_PP) / act_PP × 100 |91| MoM cancellation % | (can_CP − can_PP) / can_PP × 100 |92| MoM net growth Δ | net_CP − net_PP |9394### 2c. Churn rate9596```97monthly_churn_CP = cancellations_CP / active_subs_PP × 10098monthly_churn_PP = cancellations_PP / (active_subs at start of PP — use PP live subs)99```100101Standard SaaS convention: denominator is start-of-period active subs (use PP's102live count as the CP denominator).103104Note for dashboard: if CP is a partial month, label as "period churn rate105(N-day window)" rather than "monthly" to avoid over-stating.106107### 2d. MRR decomposition (if available)108109Call `ZohoBilling_get_mrr_insights_report` for CP. If it returns data, extract:110- New MRR (new activations)111- Expansion MRR (upgrades / add-ons)112- Contraction MRR (downgrades)113- Churned MRR (cancellations)114- Net MRR movement115116If the report returns empty or is unavailable, skip this section — don't estimate.117118### 2e. Product breakdown119120From calls #7–10, build a per-product table for **top 10 products by CP activations**.121122For each product:123- Activations CP and PP124- Cancellations CP and PP125- Net growth CP = act_CP − can_CP126- Net growth PP = act_PP − can_PP127- MoM net growth Δ128129Compute top-product activation concentration = (product_1_act / total_act_CP) × 100.130131Flag products with:132- Net negative growth in CP (cancellations > activations)133- > 20% MoM drop in activations134- Zero PP history (new product launch in CP)135136### 2f. Country breakdown137138From calls #11–14, apply the same analysis as 2e for **top 10 countries by CP total139activity** (activations + cancellations).140141For each country:142- Activations CP and PP143- Cancellations CP and PP144- Net growth CP and PP145- MoM net growth Δ146147Compute top-country activation concentration = (country_1_act / total_act_CP) × 100.148149Flag:150- Countries with net negative growth (shrinking markets)151- Countries new in CP (emerging markets — zero PP history)152- "Others" bucket if > 15% of activations (unattributed addresses)153154---155156## Step 3 — Produce the analysis output157158```markdown159## Subscription Growth — <period_label_cm> vs <period_label_lm>160161### Key Metrics162| Metric | <PP label> | <CP label> | Δ |163|---|---|---|---|164| Active subscribers | N | N | +N (+N%) |165| MRR | $X | $Y | +$Z (+N%) |166| ARPU | $X | $Y | +$Z |167| Activations | N | N | +N (+N%) |168| Cancellations | N | N | +N |169| Net growth | +N | +N | +N |170| Period churn rate | N% | N% | +Npp |171172**MRR: <direction and magnitude>. Net growth: <direction and magnitude>.**173174### MRR Decomposition (if available)175| Component | CP |176|---|---|177| New MRR | +$X |178| Expansion | +$X |179| Contraction | -$X |180| Churned | -$X |181| **Net MRR** | **+$X** |182183### Product Performance (Top 10 by CP Activations)184| Product | Act PP | Act CP | Can CP | Net CP | MoM Net Δ |185|---|---|---|---|---|---|186...187_Top-product concentration: N% of activations from "<product name>"_188189### Country Performance (Top 10 by CP Activity)190| Country | Act PP | Act CP | Can CP | Net CP | MoM Net Δ |191|---|---|---|---|---|---|192...193_Top-country concentration: N% of activations from "<country>"_194Growing: <list> Shrinking: <list>195```196197---198199## Output contract (for orchestrator)200201```json202{203 "pillar": "subscriptions",204 "metrics": {205 "active_subs_cp": <number>,206 "active_subs_pp": <number>,207 "mrr_cp": <number>,208 "mrr_pp": <number>,209 "mom_mrr_pct": <number>,210 "activations_cp": <number>,211 "activations_pp": <number>,212 "cancellations_cp": <number>,213 "net_growth_cp": <number>,214 "net_growth_pp": <number>,215 "period_churn_rate_cp_pct": <number>,216 "arpu_cp": <number>,217 "arpu_pp": <number>,218 "top_product_concentration_pct": <number>,219 "top_country_concentration_pct": <number>220 },221 "mrr_decomposition": {"new": ..., "expansion": ..., "contraction": ..., "churned": ..., "net": ...},222 "top_products": [{"name": "...", "activations_cp": ..., "net_cp": ..., "net_pp": ...}],223 "top_countries": [{"name": "...", "activations_cp": ..., "net_cp": ..., "net_pp": ...}],224 "flags": ["<shrinking markets>", "<product net negative>", "<concentration risk>"]225}226```227228---229230## Edge cases231232- **New org (< 1 month old)**: PP will be empty. Analyse CP only; note it.233- **Products with zero PP data**: label as "new product" — don't compute Δ%.234- **Churn > 100%**: impossible; if it appears, warn and skip churn scoring — denominator likely wrong.235- **MRR = 0 for free plans**: exclude from ARPU; count them separately as "free subscribers."236- **"Others" country**: include if top 10, flag as unattributed.237- **MRR decomposition unavailable**: skip the section entirely.