Subscription-box template
The Subscription-box template — a churn model for recurring physical goods built on skip / pause / payment-failure / delivery signals, reusing the order signals with no new engine math.
Pick Subscription box / recurring goods when you create a project (or apply the
template from Settings → Templates) and your dashboard is built around the two
distinctive risk buckets of box businesses: skip / pause behavior and
involuntary churn from failed cards, plus fulfillment health. It reuses the
E-commerce order_placed signal and the universal payment_failed, with
replenishment drift measured by the generic trend op — no new scoring math.
Each component maps a raw value to a 0–100 score at its good /
warn thresholds (100 at good, 30 at warn, linear between). Risk
signals (skips, pauses, failures, delivery issues, dropping cadence) are
inverse — they pull the score down as they rise. Overall health is the
weight-proportional average, banded Healthy ≥ 80 · Watch ≥ 60 · Risky ≥ 40 ·
Cold < 40.
Skip / pause & involuntary risk
The box-specific churn tells. Skipping and pausing are soft cancels that usually precede the real one, and payment failures are the single most recoverable churn bucket — involuntary churn is 20–40% of all subscription losses.
Evidence: involuntary churn from failed cards is 20–40% of subscription losses and is directly fixable with dunning and card-updater flows (Recurly). Skip/pause behaviour and delivery problems are the distinctive voluntary-churn drivers for physical boxes.
Skip rate (90d)subscription_skippedTimes the subscriber skipped a shipment.
Lower is bettergood 0warn ≥ 3weight 18
subscription_skippedTimes the subscriber skipped a shipment.
- How we collect it
- Send `subscription_skipped` when a member skips a cycle (map `subscription.skipped`).
- How to read it
- Raw value is the skip count. 0 scores 100; 3+ scores 30. Chronic skipping is the box-specific churn tell.
- How to analyze it
- Skipping is a softer signal than cancelling but predicts it — a member who skips repeatedly has usually already mentally churned.
- What to do
- Intervene after the second skip: adjust cadence, pause proactively, or offer a curation change before they cancel outright.
- Tune it
- Set warn to your product's normal skip tolerance — some boxes expect occasional skips, others don't. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Payment failures (90d)payment_failedFailed card charges in the last 90 days.
Lower is bettergood 0warn ≥ 2weight 16
payment_failedFailed card charges in the last 90 days.
- How we collect it
- Send `payment_failed` on each failed charge (map `invoice.payment_failed` / `charge.failed`).
- How to read it
- Raw value is the failure count. 0 scores 100; 2+ scores 30.
- How to analyze it
- Involuntary churn from failed cards is 20–40% of all subscription losses — and unlike voluntary churn, it's directly fixable with dunning and card-updater flows.
- What to do
- Run smart retries and a dunning sequence; prompt members to update expiring cards before the charge fails.
- Tune it
- Keep the weight high — this is the highest-ROI, most recoverable churn bucket. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Pause events (90d)subscription_pausedSubscription pauses in the last 90 days.
Lower is bettergood 0warn ≥ 2weight 14
subscription_pausedSubscription pauses in the last 90 days.
- How we collect it
- Send `subscription_paused` when a member pauses (map `subscription.paused`).
- How to read it
- Raw value is the pause count. 0 scores 100; 2+ scores 30. A pause is a soft cancel.
- How to analyze it
- Pausing is often the last step before churn — the member is testing whether they miss the box.
- What to do
- Win paused members back before the pause window ends with a reason to return, not just a reminder.
- Tune it
- Pair with skip rate; a member who both skips and pauses is your highest-risk cohort. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Fulfillment & cadence
Whether the boxes keep flowing. A declining replenishment cadence (fewer orders than before) is drift toward cancel, and delivery problems are a strong voluntary-churn driver — a member who never receives the box can't value it.
Evidence: fulfillment reliability and consistent cadence are core retention levers for physical-goods subscriptions; a broken delivery experience is among the strongest voluntary-churn drivers.
Replenishment cadence (order trend)order_placed% change in orders vs. the prior period.
Higher is bettergood ≥ 0%warn ≤ -40%weight 12
order_placed% change in orders vs. the prior period.
- How we collect it
- Uses the same `order_placed` / `shipment.sent` events, compared across two 60-day windows.
- How to read it
- Raw value is the signed % change. Flat or growing (≥ 0%) scores 100; a −40% drop scores 30.
- How to analyze it
- A declining fulfillment cadence is drift toward cancel — the member is receiving (and valuing) fewer boxes than before.
- What to do
- Catch the decline early: check for skips, delivery problems, or a lapsed card behind the drop.
- Tune it
- Widen the comparison window for infrequent boxes so a normal gap isn't read as decline. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Delivery issues (90d)delivery_issueReported delivery problems in the last 90 days.
Lower is bettergood 0warn ≥ 2weight 12
delivery_issueReported delivery problems in the last 90 days.
- How we collect it
- Send `delivery_issue` on a delivery problem (map `delivery.failed` / `shipment.issue`).
- How to read it
- Raw value is the issue count. 0 scores 100; 2+ scores 30.
- How to analyze it
- Delivery problems are a strong voluntary-churn driver for physical boxes — a member who never receives the product can't value it.
- What to do
- Resolve delivery issues fast with reships and proactive comms; a well-handled problem can even build loyalty.
- Tune it
- Lower warn if your fulfillment is normally flawless so any issue stands out. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Value & lifecycle
The commitment and activation layer. Order value rises with add-ons and upgrades, recency catches a broken cadence, and the first-box onboarding moment is the strongest early predictor of renewal.
Evidence: first-box delight and early activation strongly predict subscription renewal; expansion (add-ons / upgrades) correlates with lower churn.
Order value (90d)order_placedTotal order value in the last 90 days.
Higher is bettergood ≥ 300warn ≤ 30weight 8
order_placedTotal order value in the last 90 days.
- How we collect it
- Put the box value on the `order_placed` payload as `value`; the `sum_payload` op totals it.
- How to read it
- Raw value is summed spend, banded by your thresholds. A rising basket signals deeper commitment.
- How to analyze it
- Add-ons and upgrades raise both revenue and stickiness — high-value members churn less.
- What to do
- Offer relevant add-ons to engaged members; watch for downgrades as an early softening signal.
- Tune it
- Set the band from your box price × expected cycles per quarter. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Days since last orderorder_placedRecency of the last fulfillment.
Lower is bettergood ≤ 35 dayswarn ≥ 75 daysweight 8
order_placedRecency of the last fulfillment.
- How we collect it
- Derived from the latest `order_placed` / shipment event.
- How to read it
- Raw value is days since the last order. For a monthly box, ≤ 35d is healthy; ≥ 75d means a missed or cancelled cycle.
- How to analyze it
- A long gap between boxes is a concrete lapse — the cadence the member signed up for has broken.
- What to do
- Reach out as the gap exceeds one cycle; confirm whether it's a skip, a pause, or a silent cancel.
- Tune it
- Match good/warn to your billing cadence — weekly, monthly, or quarterly. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Onboarding in first weekonboarding_completedWhether the first-box / onboarding experience completed in the first week.
Pass / failweight 6
onboarding_completedWhether the first-box / onboarding experience completed in the first week.
- How we collect it
- Send `onboarding_completed` when the member finishes setup / receives their first box.
- How to read it
- Completed within 7 days of signup → 100; otherwise a low fixed score. A binary activation gate.
- How to analyze it
- First-box delight is the strongest early predictor of renewal — the unboxing moment sets the relationship.
- What to do
- Make the first box exceptional and the setup frictionless; recover stalled first-week onboarding fast.
- Tune it
- This is a fixed-score activation signal — adjust its weight, not a threshold. Weight, thresholds, and the metric spec are all editable in Settings → Components.
NPS / CSAT (optional)nps_responseBlended satisfaction when survey responses exist.
Higher is betterweight 6
nps_responseBlended satisfaction when survey responses exist.
- How we collect it
- Send `nps_response` / `csat_response` with a `score` payload from your survey tool.
- How to read it
- Blends NPS and CSAT into a 0–100 score when either exists; contributes nothing when absent.
- How to analyze it
- Post-box sentiment is a direct read on whether the product is landing — especially after the first few shipments.
- What to do
- Follow up on detractors quickly; a saved detractor often becomes a promoter.
- Tune it
- Keep the weight modest since survey coverage is usually partial. Weight, thresholds, and the metric spec are all editable in Settings → Components.
Sending the data
All nine components read a handful of signals. Send them via the SDK or the HTTP API; map your event names in Settings → Event map.
| Signal | When to send | Payload |
|---|---|---|
order_placed | Box shipped / order created | {"value": 39.00} for order value |
subscription_skipped | Member skips a cycle | — |
subscription_paused | Member pauses | — |
payment_failed | Charge fails | — |
delivery_issue | Delivery problem | — |
onboarding_completed | First-box / setup done | — |
subscription_resumed | Member resumes after a pause | — |
Common raw names (subscription.skipped, subscription.paused,
subscription.resumed, invoice.payment_failed, delivery.failed, …) are
pre-mapped, so most stacks resolve out of the box.
subscription_resumed isn't scored by the default template, but sending it lets
you build a custom component that rewards a recovered
subscriber — the positive counterpart to a pause.
Next
- Enrich account data — set
kind: "person"and account fields. - Build a custom dashboard — retune weights and thresholds.