All articles

Bubble + Stripe + Mailchimp: A Non-Technical Founder's Playbook

You built a product on Bubble, you charge with Stripe, you email with Mailchimp. Here's how to connect all three into one view of who signs up, who pays, and who sticks around.

TL;DR. If you built a product on Bubble, charge through Stripe, and send email with Mailchimp, you currently have three separate dashboards and no way to see the full customer. This post shows you how to export CSVs from each, join them on email, and produce one table that answers “who signed up, who paid, who opens emails, and who churned.” No code. About an hour to set up the first time.

The problem every Bubble founder has by month three

Month one: you launch. You watch signups come in through Bubble’s built-in Data view. You’re excited.

Month two: you add Stripe for payments. Now there’s a second dashboard. You cross-check it against Bubble manually — not too bad with 30 customers.

Month three: you start emailing users. Mailchimp or another tool has its own list, its own open rates, its own dashboard. Now there are three systems. You want to answer simple questions and they’re all painful:

  • Which signups converted to paid? Bubble knows who signed up, Stripe knows who paid. Nobody knows who did both.
  • Do the users who open my emails pay more? Mailchimp knows open rates; Stripe knows revenue. They don’t talk.
  • Who signed up, never paid, and never opened an email? That’s your dead-weight list — and no single dashboard will give it to you.

You can survive for a while by cross-checking manually. Somewhere between 100 and 500 users, manual breaks.

The one trick that unlocks everything: the email column

The reason this problem is solvable without engineering is that all three systems store the same email address for the same person. Bubble’s User table has email. Stripe’s Customer has email. Mailchimp’s Audience has Email Address. If you export all three and join them on email, you get a single row per human that contains everything any of the three systems knows.

That single row is the view you actually need. Once you have it, you stop guessing.

What you’ll build

A pipeline that, every time you run it, produces one CSV like this:

emailsigned_up_onpaid?planmrropens_last_30dtotal_revenuestatus
alice@example.com2026-03-12yesPro298174active paying
bob@example.com2026-03-15yesBasic9118disengaged paying
carol@example.com2026-03-18no000ghost signup
dave@example.com2026-02-01yesPro05145churned

One row per user. Four questions answered at a glance. You’ll refresh it weekly in about ten seconds.

Step 1: Export the three CSVs

From Bubble

Open the Bubble editor. Click the Data tab in the left panel, then App data. Select your User data type (or whatever type holds your signups). In the top-right of the data grid, click Upload/DownloadDownload as CSV. You want at minimum: email, created_date, and any plan or role field you store on the user.

From Stripe

Stripe Dashboard → CustomersExport. Pick the date range. The default columns are fine; make sure email, created, and id are included. Then do a second export: BillingSubscriptionsExport, including customer_email, status, plan.nickname, plan.amount, and current_period_end. For one-time payments, use the Payments export instead.

From Mailchimp

Mailchimp → AudienceAll contactsExport audience. You’ll get a zip with a CSV per list. The columns you want: Email Address, MEMBER_RATING (engagement), and the contact-level open and click counts. For campaign-level data, export a specific campaign report instead.

Step 2: Build the pipeline in Flowfile

Flowfile gives you a visual canvas where each CSV is a box and each transformation is another box. You wire them together with lines. No code.

Read and normalize emails

Drop each of the three (or four) CSVs onto the canvas as Read nodes. Add a Formula node after each one that lower-cases the email column and trims whitespace. This is the single most important step — Alice@Example.com and alice@example.com need to match, and they won’t by default.

Join Bubble + Stripe

Add a Join node. Left input: Bubble users (key = email). Right input: Stripe customers (key = email). Type: left join — you want to keep every Bubble signup, whether or not they paid. After this join, every row is a Bubble user plus their Stripe customer info if they have one.

Layer in subscriptions

Add another Join node for the Stripe subscriptions CSV, joining on stripe_customer_id (or fall back to email if you don’t store the ID on the user). Now every paying user has a plan name, MRR, and status.

Layer in Mailchimp engagement

One more Join, left input = the table you’ve built so far, right input = Mailchimp audience, key = email. After this, every user row has their open count and engagement rating.

Handle the “close but not exact” email mismatches

For the handful of users whose emails don’t exactly match across systems — a plus-sign alias, a Gmail dot variation, a typo — use a Fuzzy Match node between unmatched Bubble users and unmatched Stripe customers. Set the threshold around 0.9. This catches the roughly 1–3% of users who otherwise fall through the cracks.

Compute the status column

Add a final Formula node that labels each row based on the combination:

  • paid = yes AND opens_last_30d > 0active paying
  • paid = yes AND opens_last_30d = 0disengaged paying (churn risk)
  • paid = no AND opens_last_30d > 0warm prospect
  • paid = no AND opens_last_30d = 0ghost signup
  • subscription_status = canceledchurned

Write the output

Add a Write Data node. Export as .xlsx or .csv. Drop it in a folder you check on your usual review day.

What you do with the output

Open the CSV. Sort by status. Three action lists fall out:

  1. Disengaged paying users — paying you but not opening email. They’re the biggest churn risk. Email them individually, not via a campaign, to re-engage. This list usually predicts churn 30 days in advance.
  2. Ghost signups — no payment, no engagement. You can stop emailing them, or you can run one clearing-out campaign with a strong offer and then mark the rest inactive. Clearing ghosts raises your deliverability.
  3. Warm prospects — engaged but not paying. This is your highest-leverage list for a targeted upgrade campaign.

None of these lists exist inside Bubble, Stripe, or Mailchimp on their own. All three exist the moment you join the tables.

Automating the refresh

The CSV exports take about 90 seconds total to do by hand. Most solo founders do them weekly alongside their usual review. If that’s too much, Bubble paid plans include a data-export API, Stripe has a straightforward API, and Mailchimp has one too — Flowfile’s Python Script node can pull them directly, though that step is optional and does require a bit of setup.

For the first few months, manual exports are more than enough. The pipeline stays the same regardless of how the CSVs arrive.

Getting started

Flowfile is free, open-source, and runs on your laptop — your customer data never leaves your machine. If you want to feel the canvas before installing, the browser demo runs in any browser.

A good first pipeline: export this week’s Bubble users, Stripe customers, and Mailchimp contacts. Build the joined table above. The first time you see the “disengaged paying” list, you’ll understand the shape of your churn better than any dashboard has ever shown you.


Related reading. The 10 Numbers Every Small Business Should Track Each Week places this join pattern inside a broader weekly scorecard, and What Is a Data Pipeline? explains the underlying concept in plain English.

Frequently asked questions

I built my app on Bubble and I'm not a developer. Is this post for me?
Yes. The whole workflow here is CSV exports and a visual canvas where you drag boxes and connect them. You do not write code. If you built something on Bubble, you already handle more technical work than this pipeline requires.
Does Bubble let me export my data?
Yes. In the Bubble editor, open the Data tab, pick a data type (like User or Subscription), and click 'Upload/Download'. You get a CSV. This works on every Bubble plan, including free. For scheduled exports, the paid plans add a built-in scheduler; on free, you download manually.
Won't Stripe and Bubble already have the user's email in both systems?
Usually yes — that's what makes email the join key. When a user signs up in Bubble you ask for email; when they pay through Stripe you pass the same email. The tricky cases are capitalization differences, extra spaces, or one system lower-casing and the other not. A fuzzy-match step handles those.
Do I need to upgrade Mailchimp to use its export?
No. CSV export of audience members and campaign reports is available on Mailchimp's free plan. The limits that matter (2,500 contacts on free as of 2026) are about sending, not exporting.
What if my app is on Webflow, Softr, Glide, or Adalo instead of Bubble?
Exactly the same pattern. Any no-code platform that lets you export your user or database table to CSV plugs into this workflow. The join key is still email; the tools are still Stripe and your email provider.