Software and subscriptions
Predict cancellations and downgrades, and estimate renewal value from product usage and billing events.
Data mapping
- Entity
- account
- Group
- plan
- Profile
- generic; configure time windows with verticals.register
Supported analyses
- Will this account cancel within 30 days?
predict_event(target="cancel", window_days=30) - What is the expected value of the next renewal?
predict_value(target="renewal", window_days=365)
Reference implementation
from datetime import datetime, timedelta
from vertiq import plugins, rules
from vertiq.mapping import Mapping, apply, repair
from vertiq.tasks import predict_event, predict_value
# rows: the source export as a list of dicts, e.g. list(csv.DictReader(open("export.csv")))
mapping = Mapping.parse({"entity": "Account ID", "time": "Event Time", "type": "Event", "value": "MRR Change", "group": "Plan", "attrs": ["Seats", "Region"], "date_format": "%Y-%m-%dT%H:%M:%S"})
m, notes = repair(mapping, rows) # validates column names, value types and date format against the rows
ds, problems = apply(m, rows) # rows that fail to load are reported, not imputed
@plugins.feature("saas")
def usage_drop(entity, before, cut): # receives only events recorded before the cutoff
now = sum(1 for e in before if e.type == "login" and e.at >= cut - timedelta(days=30))
prev = sum(1 for e in before if e.type == "login"
and cut - timedelta(days=60) <= e.at < cut - timedelta(days=30))
return {"login_ratio": (now + 1) / (prev + 1)}
task = predict_event(ds, target="cancel", window_days=30, pack="saas")
print(task.status, task.report()) # "trained" only if the model outperformed the baseline on held-out entities
if task.status == "trained":
print(task.score("acct_7f2")) # probability with contributing factors
size = predict_value(ds, target="renewal", window_days=365, pack="saas")
print(size.status, size.report())
flags = rules.run(ds, [
rules.repeat(7, type="payment_failed"), # a second failed payment within seven days
])
print(flags["summary"])
This code is executed by the test suite (tests/test_guides.py) against generated records with these column names.
Recommended plugin
usage_drop: Declining product usage is an early indicator of cancellation.
Validation rules
rules.repeat(7, type="payment_failed"): a second failed payment within seven days
Related modules
insights: statistically tested patterns, such as onboarding actions associated with retentionsurvival: probability of renewal or cancellation given time since the last activitydesign: the size of control group needed to measure an onboarding change
Implementation notes
- Aggregate high-frequency usage events to daily counts before mapping.
Validation
- Every deployment: the evaluation gate measures each model on the organisation's own held-out records before promotion.