Skip to main content

Pastor cancels their Pro Website subscription

Persona

A pastor who set up their Pro Website 6–12 months ago and has decided to pause or stop. Budget constraint, switching platforms, merged with another church, or simply deprioritized. They want a clean exit in under 2 minutes without talking to support. They may want to export posts and photos before leaving.

Entry points

  1. Admin Settings → Billing — "Cancel Plan" text link.
  2. Email win-back campaign — 7-day and 30-day follow-up emails with "Reactivate" CTA; pastor may click to cancel or reactivate.
  3. Support request — pastor emails asking to cancel; support directs to self-serve flow.

Click-through flow

Steps

  1. Navigate to Admin Settings → Billing — Shows "Pro Website Bundled — $19.95/month," next billing date. "Cancel Plan" link (not a prominent button).

  2. Review cancellation note — Inline: "Your plan continues until [date]. No refunds for the current period. All data preserved — reactivate anytime." Buttons: "Manage My Subscription →" (primary) and "Nevermind" (dismisses note).

  3. Stripe Customer Portal — Stripe native cancellation: plan overview, billing period, end date, "Cancel subscription" button, optional reason dropdown. Pastor clicks "Cancel subscription." Stripe sets cancel_at_period_end = true.

  4. Receive cancellation confirmation email — Trigger: customer.subscription.updated webhook. Email: "Your ChurchWiseAI plan has been cancelled — [Church Name]," confirms end date, CTA "Reactivate here."

  5. Dashboard during cancelling period — Amber banner on every tab: "Your plan cancels on [date] — Reactivate to keep going." Full functionality remains: edit posts, upload photos, configure agents, view data. Settings → Export Data section shows "Export My Data" (green button).

  6. Optional: Export data — Downloads a ZIP: church_info.json, posts.json, requests.csv, images/ folder. If export >100MB, returns a signed URL (24h valid) via email instead of direct stream.

  7. Billing period ends → service cutoff and read-only dashboard — Stripe fires customer.subscription.deleted. Cron sets premium_churches.status = 'cancelled'. Public site shows fallback: "[Church Name]'s website is not currently active. Please contact the church directly at [phone] or [email]." Dashboard is read-only. Service ended email sent. Custom domain: held 30 days — if reactivated within window, domain is restored; if not, released.

Acceptance spec

Canonical: knowledge/acceptance/cancelled.md

Key coverage: self-serve cancellation UX, full features through period-end, read-only dashboard with export, email sequence (confirmation + 7-day/30-day win-back), public site offline state, reactivation (no second trial, all data restored).

Success criteria

  • Cancellation in under 2 minutes without contacting support.
  • No "Are you sure?" dark patterns or guilt-trip modals.
  • Site does not disappear mid-billing period.
  • Public site shows polite fallback message (not a 404).
  • Reactivation is one click away from email or dashboard.

Known failure modes

  • customer.subscription.deleted webhook fails. Inbox pattern retries with backoff. Verify cron is processing the event. Source: memory/project_stripe_webhook_inbox.md.

  • Read-only mode not enforced. Forms must be server-side gated: PUT /api/premium/posts/[id] should return 403 if premium_churches.status = 'cancelled'.

  • Export file too large. If ZIP >100MB, stream fails. Return signed URL email fallback instead of direct download.

  • Custom domain left pointing at ChurchWiseAI. Post-cancellation, CNAME still resolves to Vercel (404 or fallback). Include DNS cleanup instructions in the service-ended email.

  • Reactivation creates a duplicate premium_churches row. Reactivation logic must check for existing cancelled row first and reuse it (set status='active') rather than inserting a new row.