Mixpanel Funnel + Stripe Trial Conversion: Daily Cohort Health Digest to Slack via n8n
Every morning, join Mixpanel's trial activation data with Stripe's conversion data for the same cohort and push one digest to Slack — so you know in 30 seconds whether activation or billing is killing your trials.
The stack in the order it runs — data flows from the source through to where it lands.
The most common blind spot in SaaS ops: product says activation is fine, finance says conversion is down, and nobody can tell whether the problem is in-product behavior or the billing step. The data lives in two places. Nobody joins it manually more than once a quarter.
n8n is the right call here because this workflow needs conditional logic and light data transformation between API calls — specifically joining two datasets on user ID or email. n8n's Function nodes let you write real JavaScript for that join. It also self-hosts cleanly if you're cautious about sending user cohort data to a third-party SaaS automation platform.
Mixpanel's Query API (`/funnels`) returns step-by-step conversion for a defined date range. Stripe's `/v1/subscriptions` endpoint filtered by `status=trialing` and a `trial_end` date range gives you trials expiring in the next 7 days and which ones converted. You don't need a data warehouse — n8n holds the join in memory for a daily digest.
One real tradeoff: Mixpanel's API rate limits are 60 queries/hour on the free/growth plan. This workflow makes 2–3 calls per run, so you're fine there. The bigger risk is that Mixpanel user IDs and Stripe customer emails may not match. You need Mixpanel's `$email` property set during `identify()` calls for the join to work. If your Mixpanel events don't include email, the join breaks and you need a Segment intermediary. Also — skip this entire workflow if you have more than ~10,000 trial users. At that volume the in-memory join in n8n becomes unreliable. Pipe both sources into Supabase and run SQL instead.
The stack (4)
How it runs
- 1
Set up the n8n workflow with a daily CRON trigger
Create a new workflow in n8n. Add a Schedule Trigger node set to run at 8:00 AM in your local timezone every day. Name it `trial-cohort-health-digest`. Be explicit about the timezone — n8n defaults to server timezone, which is usually UTC. A digest hitting Slack at 3 AM gets ignored.
- 2
Query Mixpanel funnel conversion for the last 7 days
Add an HTTP Request node. Method: GET. URL: `https://mixpanel.com/api/2.0/funnels`. Auth: Basic auth with your Mixpanel API Secret as the username, empty password. Params: `funnel_id` (pull this from your Mixpanel funnel URL), `from_date` set to today minus 8 days, `to_date` set to today minus 1 day, `unit=day`. The response includes per-step counts and conversion rates. Wire a Function node after it to parse the `steps` array and extract step names, counts, and the overall funnel conversion rate.
- 3
Query Stripe for trials ending in the next 7 days and their status
Add a second HTTP Request node. Method: GET. URL: `https://api.stripe.com/v1/subscriptions`. Auth: Bearer with your Stripe secret key. Params: `status=trialing`, `trial_end[gte]` = today's Unix timestamp, `trial_end[lte]` = today + 7 days Unix timestamp, `limit=100`. Make a second call for `status=active` subscriptions where `metadata.converted_from_trial=true` if you tag conversions, or filter by `created` date range. This gets you trials-in-flight and recent converts.
- 4
Join Mixpanel and Stripe data on email in a Function node
Add a Function node. Build two maps: one from Stripe `customer.email → subscription status`, one from Mixpanel's user-level funnel data if you're using the Engage API — or use aggregate counts if not. For an aggregate digest, calculate: `trialsInFlight`, `trialsConvertedThisWeek`, `trialConversionRate`, `mixpanelActivationRate` (step 1 → final step). High activation rate paired with low conversion rate means billing or pricing friction — not a product problem. Document this logic in an n8n Sticky Note so whoever inherits the workflow doesn't have to reverse-engineer it.
- 5
Calculate the cohort health score and flag anomalies
In the same Function node or a chained one, compute a simple health score: `trialConversionRate < 15%` flags RED, 15–25% flags YELLOW, >25% flags GREEN. Do the same for `mixpanelActivationRate` using thresholds based on your historical baseline — hardcode them to start, refine after 30 days of data. Store both flags. If either is RED, set `alertRequired = true`.
- 6
Build the Slack Block Kit message
Add a Function node to construct the Slack payload. Structure it as: a header with the date range, a two-column section showing Mixpanel activation rate vs. Stripe trial conversion rate, a Diagnosis line (e.g., "Activation OK, Conversion Low → check pricing page or trial-end email sequence"), and a footer with raw counts. Use emoji status indicators. Keep it under 15 lines — if someone has to scroll, they won't read it.
- 7
Post to Slack with conditional urgency
Add a Slack node using n8n's built-in Slack integration with your Bot Token. Always post to `#product-ops`. Add an IF node before the Slack node: if `alertRequired = true`, route to a second Slack node that posts to `#alerts` and includes an @here or a specific user mention. The digest always hits the ops channel. It only pages people when a threshold is actually breached.
- 8
Add error handling for API failures
Add an Error Trigger node in n8n connected to a final Slack node that posts to `#ops-errors` if the workflow fails. The most common failure points are Mixpanel rate limits and Stripe API timeouts. Add a Wait node with a 2-second delay before each HTTP call to reduce burst issues. Include the error message in the Slack notification — whoever sees it needs to diagnose the problem without opening n8n.
Want me to build this for you instead?
Product Audit and CTO Mode run out of this same thinking. If you’re reading this thinking “I want this, but in my product” — let’s talk.
See servicesMore like this
Google Analytics 4 + HubSpot Lifecycle Stage: Weekly Acquisition-Quality Digest to Slack via Pipedream with Claude Narrative
Stop reporting traffic numbers. Report whether the traffic you paid for last week actually became pipeline — with a one-paragraph executive summary written by Claude.
Gmail Thread Aging + Stripe Invoice Overdue: Unified AR Follow-Up Digest to Slack via Zapier
Surface overdue Stripe invoices and the exact age of your last Gmail thread with that customer — every morning at 8:30, automatically — so AR follow-up stops living in someone's head.
Intercom Ticket Volume + Razorpay Failed Payments: Daily Support-Cost-per-Revenue Alert to Slack via Zapier
Catch the support cost blowout from Razorpay failed payments before your agents are already buried.